使用延迟加载替换Eager Loading

时间:2013-01-20 19:29:02

标签: .net performance entity-framework c#-4.0 entity-framework-4.1

如何使用Eager Loading替换Lazy loading

让我们这样说。我有很多Include keys以下的EF查询。性能明智非常慢

那么如何使用Lazy loading

来提高以下代码的性能
from owner in Catalog.Owners
            where owner.Key == ownerKey
            from invoice in owner.Invoices
            where invoice.Provider.Key == providerKey
            where invoice.Id == id
            select invoice)
            .Include(i => i.Owner.Credits)
            .Include(i => i.Provider)
            .Include(i => i.Items.Select(s => s.Allocation.Service))
            .Include(i => i.Items.Select(s => s.Allocation.Pet))
            .FirstOrDefault();

如果你能给我一个示例代码说明,那就完美了。

2 个答案:

答案 0 :(得分:2)

使用EF 4.1及更高版本,您只需确保将代码优先导航属性(链接到其他实体的属性)定义为virtual。然后,如果您在DbContext内,则只有在实际使用(延迟加载)数据库时才会查询链接实体。

但是,如果您想立即获取所有数据,则会使用急切加载。通常有很好的理由。所以,我首先要说的是,如果你不知道为什么你急于加载,那么就不要这样做。确保链接实体的属性是虚拟的,然后删除查询中的.Include语句。

但是,如果您正在查询DbContext以外的数据,或者您立即使用数据,则在操作期间将数据提取到内存中是有意义的。

因此,在回答您的问题时,并不总是只需用eager加载替换lazy加载。您必须查看查询后对数据执行的操作,并了解如何仅返回所需的最小数据集。

添加了示例:

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Car> Cars { get; set; } //make it virtual

    }

    public class Car
    {
        public int Id { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
    }

    public class MyContext : DbContext
    {
        public IDbSet<Person> People { get; set; }
        public IDbSet<Car> Cars { get; set; }
    }

    class Program
    {
        private static void Main(string[] args)
        {
            using (var context = new MyContext())
            {
                var person = context.People.FirstOrDefault(p => p.Id == 1); // calls the database

                var car = person.Cars.FirstOrDefault(c => c.Id == 2); // Lazy loads Cars

            }
        }
    }

答案 1 :(得分:2)

如果您不使用预先加载(Include调用),如果您正确设置了所有内容,将自动使用延迟加载:

  • virtual导航属性
  • 允许延迟加载和代理创建(默认情况下应该是这样)
  • 在用于加载根对象的对象上下文范围内执行的延迟加载

延迟加载仅在您访问导航属性时才执行查询以加载相关实体,因此它可以提高性能,例如,如果您不需要所有相关数据,但如果您需要它们总是会导致更糟糕的情况由于大量数据库往返而导致的性能。