N 层应用程序上的实体框架自跟踪实体
这是一个一般性的架构问题,希望对于已经在最终应用程序中使用 EF 的人们来说是这样。
我们有一个典型的 N 层应用程序:
- WPF 客户端
- WCF 服务
- EF STE DTO 的
- EF 数据层
该应用程序在加载时(在用户登录的同时)加载所有已知的业务类型,然后在上加载一个非常大的“工作批次”根据需求,该批次约为 4-8Mg,由 1000 多个业务对象组成。当我们完成加载此“批次”时,我们会将所有内容与之前加载的业务类型链接起来,等等...
最后,我们在内存中拥有大约 2K-5K 业务对象,全部正确引用,因此我们可以在客户端使用和滥用 LINQ ,我们还在客户端对所有这些对象进行一些复杂的数学计算,所以我们确实需要大图。
当我们想要保存对数据库的更改时,问题就出现了。有了如此大的对象图,我们几乎不想通过网络再次发送所有内容。
考虑到到目前为止 T4 模板的复杂性,我们目前的方法是在更新时分离和附加所有内容,但我不喜欢这种方法。我们基本上想要更新给定的对象,将其与图的其余部分分离,通过网络发送它,在 WCF 端更新它,然后在客户端再次重新附加它。主要问题是,当您想要更新链接对象时,假设您添加了一些对已添加的内容有引用的内容,然后又添加了对已修改内容的另一个引用,等等。这会迫使大量客户端代码确保我们不会这样做。不要破坏任何东西。
所有这些都是通过生成的代码完成的,因此我们讨论的是每个模板 200-800 行 T4 代码。
我现在正在研究的是一种自定义 STE 的序列化和反序列化的方法,以便我可以控制通过网络发送或不发送的内容,并且能够批量更新而不仅仅是单个 STE。检查引用,看看这些引用是否未更改;如果不是,则不要序列化,如果是,则序列化并更新所有内容,只需将其附加到 WCF 端的上下文即可。
经过一番研究,我发现了这种方法的两种解决方案。
一种是编写自定义 DataContractSerializer。
第二种是通过更改 EF 创建的 STE 模板并使用 KnownTypeAttribute,而不是为每个引用类型生成它,而是让它引用一个检查对象的方法,并仅标记未更改的序列化引用。
- 有没有人遇到过这个 之前的问题?
- 您使用了什么解决方案?
- 下来你遇到了什么问题 线?
- 维护起来有多容易 模板已创建?
This is a general architecture question, hopefully to folks out there already using EF in final applications.
We have a typical N-Tier application:
- WPF Client
- WCF Services
- EF STE DTO's
- EF Data Layer
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. 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.
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. 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. 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.
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. 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.
After some studying I found 2 solutions to this method.
One is by writing a custom 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.
- 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不知道整个应用程序设计,但如果您通常将工作批加载到服务,然后将其发送到客户端来使用它,看起来服务层在某种程度上是不必要的,您可以直接从数据库加载数据(并且您将获得更好的性能)。根据计算的复杂性,您还可以直接在数据库中进行一些计算,您将再次获得更好的性能。
您只保存部分图表的方法是对 STE 概念的滥用。 STE 的工作方式是 - 加载图表、修改图表并保存相同的图表。如果您希望有一个大数据集用于读取并仅保存小块,那么最好加载数据集以供读取,一旦您决定更新一个块,只需再次加载该块,修改它并将其发回。
恕我直言,干扰内部 STE 行为是在某些角落/意外情况下丢失某些更改的最佳方法。
顺便提一句。这在某种程度上看起来像是将本地数据库与全局数据库同步的场景 - 我从未这样做过,但它在智能客户端中很常见。
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 works in manner - you load the graph, modify the graph and save the same graph. 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.
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.