简体   繁体   English

N层应用程序上的实体框架自我跟踪实体

[英]Entity Framework Self Tracking Entities on a N-Tier application

This is a general architecture question, hopefully to folks out there already using EF in final applications. 这是一个通用的体系结构问题,希望对已经在最终应用中使用EF的人们有所帮助。

We have a typical N-Tier application: 我们有一个典型的N层应用程序:

  • WPF Client WPF客户端
  • WCF Services WCF服务
  • EF STE DTO's EF STE DTO的
  • EF Data Layer EF数据层

The application loads all known business types during load time (at the same time as the user logs in) then loads a very large "Work Batch" on demand, this batch is around 4-8Mg and is composed of over 1.000 business objects. 该应用程序在加载期间(在用户登录的同时)加载所有已知的业务类型,然后按需加载非常大的“工作批次”,该批次大约为4-8Mg,由超过1.000个业务对象组成。 When we finish loading this "Batch" we then link everything with the previously loaded business types, etc... 当我们完成加载此“批处理”时,我们将所有内容与先前加载的业务类型等链接起来。

In the end we have around 2K-5K business objects in memory all correctly reference so we can use and abuse LINQ on the client side, we also do some complex math on all these objects on the client side, so we really need the large graph. 最后,我们在内存中大约有2K-5K个业务对象都可以正确引用,因此我们可以在客户端使用和滥用LINQ,我们还在客户端上对所有这些对象进行一些复杂的数学运算,因此我们确实需要大图。

The issue comes when we want to save changes to the Database. 当我们想要将更改保存到数据库时,问题就来了。 With such a large object graph, we hardly want to send over everything again through the Network. 有了如此大的对象图,我们几乎不想通过网络再次发送所有内容。

Our current aproach, which I dislike, given the complexity of the T4 templates so far, is to detach and attach everything on update. 考虑到到目前为止T4模板的复杂性,我当前不喜欢的方法是分离并附加更新中的所有内容。 We basically want to update a given object, detach it from the rest of the graph, send it over the network, updated it on the WCF side, and then reattach it again on the client side. 我们基本上想更新一个给定的对象,将其与图的其余部分分离,通过网络发送,在WCF端进行更新,然后在客户端再次进行附加。 The main problem is when you want to update linked objects, let's say you add something that has a reference for something that is also added, then another reference to something modified, etc. This forces a lot of client code to make sure we don't break anything. 主要问题是,当您要更新链接的对象时,假设您添加的对象具有对也要添加的对象的引用,然后又添加了对已修改的对象的引用,等等。这迫使许多客户端代码确保我们不这样做。不要破坏任何东西。

All this is done with generated code, so we are talking about 200-800 lines of T4 code per template. 所有这些操作都是通过生成的代码完成的,因此我们正在谈论每个模板200-800行的T4代码。

What I'm looking at right now is a way to customize serialization and deserialization of the STE's, so that I can control what is sent over the network or not, and be able to update batches instead of just a single STE. 我现在正在查看的是一种自定义STE序列化和反序列化的方法,这样我就可以控制是否通过网络发送了什么,并且能够更新批处理,而不仅仅是一个STE。 Checking references, see if those references are Unchanged or not; 检查参考,查看这些参考是否未更改; if not don't serialize, if yes serialize and update everything just by attaching it to the context on the WCF side. 如果不是,则不进行序列化;如果是,则不进行序列化,只需将其附加到WCF端的上下文即可进行序列化和更新。

After some studying I found 2 solutions to this method. 经过研究,我发现了该方法的两种解决方案。

One is by writing a custom DataContractSerializer. 一种是编写自定义DataContractSerializer。

The second one is by changing the STE template created by EF and playing around with the KnownTypeAttribute, instead of generating it for each reference type, have it reference a method that inspects the object and only marks for serialization references that are not unchanged. 第二个方法是通过更改由EF创建的STE模板并使用KnownTypeAttribute,而不是为每种引用类型生成它,而是让它引用一种检查对象的方法,并仅标记未更改的序列化引用。

  • Has anyone ever come across this issue before? 有人遇到过这个问题吗?
  • What solutions did you use? 您使用了什么解决方案?
  • What problems did you encounter down the line? 您到底遇到了什么问题?
  • How easy was it to maintain the templates created? 维护创建的模板有多容易?

I don't know whole application design but if you generally load the work batch to the service and then send it to the client to play with it, it looks like service layer is somehow unnecessary and you can directly load data from database (and you will get much better performance). 我不知道整个应用程序的设计,但是如果您通常将工作批加载到服务中,然后将其发送给客户端以进行使用,则看起来服务层似乎是不必要的,您可以直接从数据库加载数据将会获得更好的性能)。 Depending on complexity of computation you can also do some computation directly in the database and you will again get much better performance. 根据计算的复杂性,您还可以直接在数据库中进行一些计算,您将再次获得更好的性能。

Your approach to save only part of the graph is abuse to STE concept. 您只保存部分图表的方法是滥用STE概念。 STE works in manner - you load the graph, modify the graph and save the same graph. STE的工作方式-您加载图形,修改图形并保存相同的图形。 If you want to have a big dataset for reading and save only small chunks it is probably better to load data set for reading and once you decide to update a chunk, load only the chunk again, modify it and send it back. 如果您想拥有一个较大的数据集以读取并仅保存小块,则最好加载要读取的数据集,一旦决定更新一个块,则仅再次加载该块,然后对其进行修改并发送回去。

Interfering the internal STEs behavior is imho the best way to lost some changes in some corner / unexpected scenarios. 干扰内部STE行为是在某些转角/意外情况下丢失某些更改的最佳方法。

Btw. 顺便说一句。 this somehow looks like a scenario for syncing local database with a global one - I have never done that but it is quite common in smart-clients. 这种方式看起来像是一种将本地数据库与全局数据库同步的方案-我从未做过,但是在智能客户端中很常见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM