WCF数据序列化:它能走得更快吗? [英] WCF data serialization : can it go faster?

查看:135
本文介绍了WCF数据序列化:它能走得更快吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是那个的问题。

当我们要构建一个适用于某种数据的WCF服务时,很自然,我们希望它能够快速高效。为了实现这一点,我们必须确保数据公路旅行的所有部分尽可能快地从数据存储后端(如SQL Server)到请求数据的WCF客户端。

When we want to build a WCF service which works with some kind of data, it's natural that we want it to be fast and efficient. In order to achieve that, we have to make sure all segments of data road trip work as fast as they could, from data storage back-end such as SQL Server, to a WCF client who requested that data.

在寻求上一个问题的答案的同时,感谢 Slauma 以及通过注释贡献的其他人,实体框架(第一)大查询的耗时部分是对象实现,并在返回数据库的结果时将实体附加到上下文。我们已经看到,后续查询中的所有内容都能更快地运行。

While seeking for an answer on that previous question, we have learned, thanks to Slauma and others who contributed through comments, that the time consuming part of Entity Framework's (first) large query is object materialization and attaching entities to the context when the result from the database is returned. We have seen that everything works much faster on subsequent queries.

假设这些大型查询被用作只读操作,我们得出结论,我们可以设置EF MergeOption NoTracking ,产生更好的第一个查询性能。我们使用 NoTracking 做的是告诉EF为从数据库检索的每个记录创建单独的对象 - 即使它们具有相同的键。如果我们的查询中有 .Include()语句,这将导致额外的处理,这将导致返回的大小更大的数据。

Assuming those large queries are used as read-only operations, we came to a conclusion that we could set EF MergeOption to NoTracking, yielding better first query performance. What we have done with NoTracking was telling EF to create separate object for each record retrieved from the database - even when they have the same key. This will cause additional processing if we have .Include() statement in our query, which will lead to data with much larger size being returned.

数据可能太大了,我们可以很容易地问自己 - 使用 NoTracking 选项,我们是否真的帮助我们的事业,即使我们做了查询更快(也可能只有第一个,取决于 .Include()语句的数量,因为后续的查询没有 NoTracking 选项与多个 .Include()语句运行速度更快,因为 NoTracking 选项会导致创建更多的对象数据从服务器返回)?

The data may be so big that we could easily ask ourselves - did we really help our cause by using NoTracking option, even if we made the query faster (and maybe only the first one, depending on the number of .Include() statements, because subsequent queries without NoTracking option with multiple .Include() statements run faster simply because NoTracking option causes a lot more objects to be created when data returns from the server)?

最大的问题是如何有效地序列化这个数据量,并在客户端上反序列化。与序列化一样缓慢(我使用 DataContractSerializer PreserveObjectReferences 设置为 true 因为我将EF 4.x生成的POCO发送到我的客户端,反之亦然),我们想要生成更多的数据(感谢 NoTracking )?说实话,我没有看到来自这个查询的数据,在〜11.000个对象上的 NoTracking 选项不包括通过获得的导航属性.Include( ),到达客户端。最后一次我试图把它关闭,超时时间是00:10:00被触发(!)

The biggest problem is how to efficiently serialize this amount of data - and deserialize it on the client. With serialization already as slow as it is (I am using DataContractSerializer with PreserveObjectReferences set to true because I am sending EF 4.x generated POCOs to my client and vice versa), do we want to generate even more data (thanks to NoTracking)? To be honest, I haven't seen the data originated from the query with NoTracking option on ~11.000 objects not including navigation properties obtained via .Include(), arriving at the client side yet. Last time I tried to pull this off, the timeout of 00:10:00 was triggered (!)

所以如果你还在读这个文本墙,你会告诉我如何解决这个情况。要使用哪个serializer才能达到可接受的结果?目前,如果我不使用 NoTracking 选项,通过 wsHttpBinding 的序列化,传输和反序列化〜11.000在本地机器上的自定义绑定需要〜5秒。对我而言恐怕是这个大桌子最有可能包含〜500.000条记录。

So if you are still reading this wall of text, you tell me how to solve this situation. Which serializer to use in order to achieve acceptable results? Currently, if I don't use the NoTracking option, the serialization, transport and deserialization of ~11.000, via wsHttpBinding-like custom binding on the local machine take ~5 seconds. What's scary to me is that this large table is most likely going to contain ~500.000 records eventually.

推荐答案

查看您的对象模型,并在select语句中进行投影。这应该快很多了:

Have you considered creating a View Model for your object and doing a projection in the select statement. That should be a lot faster so:

 var result = from person in DB.Entities.Persons
    .Include("District")
    .Include("District.City")
    .Include("District.City.State")
    .Include("Nationality")
    select new PersonViewModel()
    {
        Name = person.Name, 
        City = person.District.City, 
        State = person.District.City.State
        Nationality = person.Nationality.Name
    };

这将需要您创建一个ViewModel类来保存PersonViewModel的展平数据。

This would require you to create a ViewModel class to hold the flattened data for the PersonViewModel.

您可以通过创建数据库视图并直接从中选择实体框架来进一步加快事宜。

You might be able to further speed up things by creating a database view and letting Entity Framework select directly from there.

如果您反弹希望前端使用500.000条记录填充网格,那么我将完全删除Web服务层,并使用DataReader来加快进程。实体框架和WCF不适合以适当的性能转换数据。你在这里基本做的是:

If you rally want the front-end to populate a grid with 500.000 records, then I'd remove the webservice layer altogether and use a DataReader to speed up the process. Entity Framework and WCF aren't suitable for transforming the data at a proper performance. What you're basically doing here is:


数据库 - > TDS - > .NET对象 - > XML - >纯文本 - > XML - > .NET对象 - > UI

Database -> TDS -> .NET objects -> XML -> Plain text -> XML -> .NET Objects -> UI

虽然这可以很容易地减少到:

While this could easily be reduced to:


数据库 - > TDS - > UI

Database -> TDS -> UI

然后使用EntityFramwork来处理您的业​​务逻辑中的实体。这与命令和查询分离模式相一致。使用适合高性能查询数据的技术,并直接链接到您的应用程序。然后使用命令策略实现您的业务逻辑。

Then use EntityFramwork to handle the changes to the entities in your business logic. This is in line with the Command and Query Separation pattern. Use a technology suitable for high performance querying of data and link that directly to your app. Then use a command strategy to implement your business logic.

OData服务还可能提供一种更好的方式将UI直接链接到数据,因为它可以用于快速查询您的数据,允许您实现快速过滤,而无需用户真正注意。

OData services might also provide a better way to link your UI directly to the data, as it can be used to quickly query your data allowing you to implement quick filtering without the user really noticing.

如果安全设置禁止通过OData直接查询或直接访问SQL数据库,请考虑实现对象自己直接从视图或查询中选择数据,并使用 IDataReader 直接填充您的ViewModel。这可能会给你最高的性能。

If the security settings are prohibiting direct querying through OData or direct access to the SQL database, consider materializing the objects yourself. Select the data directly from either a view or a query and use a IDataReader to directly populate your ViewModel. That will probably give you the highest performance.

创建实体框架有很多替代方法,特别是因为没有为大型数据集剪切EF。请参阅 FluentData DapperDotNet 大规模 PetaPoco 。您可能希望与实体框架并行使用这些并行处理您的大型平面数据查询。

There are a lot of alternatives to Entity Framework created especially because EF isn't cut out for large datasets. See FluentData DapperDotNet, Massive or PetaPoco. You might want to use these side-by-side with entity Framework to handle your large, flat data queries.

这篇关于WCF数据序列化:它能走得更快吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆