【问题标题】:Workaround for the performance issue caused by the include statement from EntityFramework DbSetEntityFramework DbSet 中的 include 语句导致的性能问题的解决方法
【发布时间】:2012-08-24 15:04:45
【问题描述】:

在我的应用程序中,我首先使用 SQL CE 4.0 和实体框架代码。

public class Customer : IEntityPoco
{
    public  int Id { get; set; }

    public  string Sex          { get; set; }
    public  string Titel        { get; set; }
    public  string FirstName    { get; set; }
    public  string SecondName   { get; set; }
    public  string LastName     { get; set; }
    public  string Fax          { get; set; }
    public  string Notice       { get; set; }
    public  DateTime LastChange { get; set; }

    public  int AddressId   { get; set; }
    public  Address Address { get; set; }

    public  ICollection<Sale> Sales { get; set; }
    public  ICollection<Customer> Partner1 { get; set; }
    public  ICollection<Customer> Partner2 { get; set; }
    public  ICollection<Phone> PhoneNumbers { get; set; }
    public  ICollection<Email> EmailAddresses { get; set; }
    public  ICollection<Corrospondence> Corrospondence { get; set; }
    public  ICollection<ShippingAddress> ShippingAddresses { get; set; }
}

这就是我的模型的样子,

var query = context.TeacherCustomers
    .Include(i => i.EmailAddresses)
    .Include(i => i.Corrospondence)
    .Include(i => i.Address.City.Country)
    .Include(i => i.ShippingAddresses)
    .Include(i => i.Sales.Select(f => f.BuildVersion.Product))
    .Include(i => i.PhoneNumbers)
    .Include(i => i.Partner1.Select(f => f.Address.City.Country))
    .Include(i => i.Partner2.Select(f => f.Address.City.Country))
    .AsNoTracking();

这就是我的查询的样子。在我的业务逻辑中,我需要所有电子邮件地址、电话号码……如果我评论所有包含语句,则此查询将在大约 82 毫秒内执行,如果未评论所有包含语句,则查询大约需要 52000 毫秒(而且它不是第一个查询所以数据库模型已经编译好了)。

这里的这篇文章很好地解释了这个问题:How many Include I can use on ObjectSet in EntityFramework to retain performance?,但是给定的解决方案对我来说也不是一个选项,因为我的数据库包含超过 10 000 个条目,当我执行查询然后单步执行所有返回的客户时通过查询和调用 context.Entry(customer).Reference(i => i.EmailAddresses).Load() 也需要很多时间。

那么我怎样才能创建一个与上述查询具有相同结果但执行速度更快的查询呢?

我们将不胜感激

【问题讨论】:

  • 你试过没有AsNoTracking吗?就性能而言,它可能会适得其反:stackoverflow.com/a/9843614/270591 但它可能不会有太大的不同。您对数据库中所有涉及的 FK 都有适当的索引吗?
  • 没有 AsNoTracking 会更糟。关于索引我不确定。完整的数据库是从 DbContext 生成的。所有关系都有一个外键属性。

标签: entity-framework include sql-server-ce


【解决方案1】:

我不确定您是否能够从该模型中获得很多性能。您实际上是在交叉连接所有表,这将为您提供一个巨大的表和大量记录。

我建议重新考虑您的模型,可能会有点反规范化,您真的需要电子邮件表格吗?电话号码不能只是表格中的多个列(大多数应用程序不需要超过 2 个邮件或电话号码) .

如果您对模型无能为力,我建议单独加载所有表,例如使用一个查询加载所有客户,一个查询加载所有电子邮件等等,然后将它们加入模型中。根据您提供的统计数据,加载所有数据只需不到 400 毫秒。

【讨论】:

  • 感谢您的快速回复。您认为使用另一个 OR Mapper 会更快吗?可能的 NHibernate?
猜你喜欢
  • 2020-06-27
  • 2010-09-11
  • 1970-01-01
  • 2021-08-09
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多