1

这个问题有点像那个问题的续集。

当我们想要构建一个处理某种数据的 WCF 服务时,我们自然希望它快速高效。为了实现这一点,我们必须确保数据之旅的所有部分都尽可能快地工作,从 SQL Server 等数据存储后端到请求该数据的 WCF 客户端。

在寻求上一个问题的答案时,我们了解到,感谢Slauma和其他通过评论做出贡献的人,Entity Framework 的(第一个)大型查询的耗时部分是对象物化并将实体附加到上下文,当结果来自返回数据库。我们已经看到,在后续查询中,一切都运行得更快。

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

数据可能是如此之大,以至于我们可以很容易地问自己——我们是否真的通过使用NoTracking选项来帮助我们的事业,即使我们使查询更快(可能只有第一个,取决于.Include()语句的数量,因为后续查询没有NoTracking选项使用多个.Include()语句运行得更快仅仅是因为NoTracking选项会导致在数据从服务器返回时创建更多的对象)?

最大的问题是如何有效地序列化这些数据量——并在客户端进行反序列化。序列化已经很慢了(我使用DataContractSerializerwith PreserveObjectReferencesset totrue是因为我将 EF 4.x 生成的 POCO 发送给我的客户端,反之亦然),我们是否想要生成更多数据(感谢NoTracking)?老实说,我还没有看到来自查询的数据,该查询带有NoTracking~11.000 个对象的选项,不包括通过 获得的导航属性.Include(),但尚未到达客户端。上次我试图解决这个问题时,触发了 00:10:00 的超时(!)

所以如果你还在看这面文字墙,你告诉我如何解决这种情况。使用哪个序列化程序来获得可接受的结果?目前,如果我不使用该NoTracking选项,则 ~11.000 的序列化、传输和反序列化,通过wsHttpBinding本地机器上的类似自定义绑定需要 ~5 秒。让我害怕的是,这个大表最终很可能会包含约 500.000 条记录。

4

3 回答 3

3

您是否考虑过为您的对象创建一个视图模型并在 select 语句中进行投影。那应该快很多,所以:

 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 的展平数据。

您可以通过创建数据库视图并让 Entity Framework 直接从那里选择来进一步加快速度。

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

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

虽然这可以很容易地简化为:

数据库 -> TDS -> 用户界面

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

OData 服务还可能提供更好的方式将您的 UI 直接链接到数据,因为它可用于快速查询您的数据,从而允许您在用户没有真正注意到的情况下实现快速过滤。

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

实体框架有很多替代品,特别是因为 EF 不适用于大型数据集。请参阅FluentData DapperDotNetMassivePetaPoco。您可能希望将这些与实体框架并排使用来处理您的大型平面数据查询。

于 2012-04-04T19:33:02.143 回答
0

我在我的 RIA 应用程序中使用 Json.Net 的 Bson 实现。更多信息在这里。

当我从数据库中读取数据并序列化行时,我将返回一个 IEnumerable。我发现速度是可以接受的,我返回的实体大约有 20 个属性。这种方法应该最大限度地减少服务器上的并发内存使用。

于 2012-04-04T19:40:33.023 回答
0

根据我通过查看各种评论和性能基准收集到的信息,我会选择protobuf-net作为序列化程序。是否可以插入到我的服务配置中只是设计问题。更多关于这里的信息。

虽然不完全是这个问题的答案,但jessehouwing 给出了最好的答案,我将其标记为已接受。

于 2012-04-07T07:02:29.073 回答