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. When we finish loading this "Batch" we then link everything with the previously loaded business types, etc...
应用程序在加载时加载所有已知的业务类型(同时用户登录),然后根据需要加载一个非常大的“工作批次”,这批大约4-8Mg,由超过1,000个业务对象组成。当我们加载完这个“批处理”后,我们将所有内容与先前加载的业务类型链接在一起……
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. 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.
由于T4模板的复杂性,我不喜欢目前的aproach,它是在更新时分离和附加所有内容。我们主要想要更新一个给定的对象,将它从图的其余部分分离出来,通过网络发送,更新到WCF端,然后再在客户端重新连接。主要的问题是,当你想要更新链接对象时,假设你添加了一些有引用的东西,这些东西也被添加了,然后是对一些修改过的东西的引用,等等。这就迫使很多客户端代码确保我们不会破坏任何东西。
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. 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.
我现在看到的是一种定制STE的序列化和反序列化的方法,这样我就可以控制通过网络发送的内容,并且能够更新而不仅仅是单个的STE。检查引用,看看这些引用是否没有变化;如果不是串行化,如果是串行化,通过将它附加到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?
- 维护创建的模板有多容易?
1 个解决方案
#1
0
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.
您只保存图的一部分的方法是对STE的概念的滥用。STE的工作方式是:加载图形、修改图形并保存相同的图形。如果你想要一个大的数据集用于读取并且只保存小块,那么最好是加载数据集用于读取,一旦你决定更新一个块,就只加载这个块,修改它并将它发送回来。
Interfering the internal STEs behavior is imho the best way to lost some changes in some corner / unexpected scenarios.
干扰内部STEs行为是在某些角落/意想不到的场景中丢失一些更改的最好方法。
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.
顺便说一句。这看起来就像是同步本地数据库和全局数据库的场景——我从来没有这样做过,但在智能客户端很常见。
#1
0
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.
您只保存图的一部分的方法是对STE的概念的滥用。STE的工作方式是:加载图形、修改图形并保存相同的图形。如果你想要一个大的数据集用于读取并且只保存小块,那么最好是加载数据集用于读取,一旦你决定更新一个块,就只加载这个块,修改它并将它发送回来。
Interfering the internal STEs behavior is imho the best way to lost some changes in some corner / unexpected scenarios.
干扰内部STEs行为是在某些角落/意想不到的场景中丢失一些更改的最好方法。
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.
顺便说一句。这看起来就像是同步本地数据库和全局数据库的场景——我从来没有这样做过,但在智能客户端很常见。