EntityFramework - 加载方式

引用自: http://www.cnblogs.com/nianming/p/3494781.html

 

EF 关联实体加载方式有三种

Lazy Loading 

Eager Loading

Explicit Loading

其中: Lazy Loading 是自动延迟加载 Explicit Loading是手动延迟加载

 

Lazy Loading 

在用到具体数据的时候才会加载进内存

当使用 ToList() 或者直接使用 List<> 接受数据时不会引发懒加载

必要的条件是:

1. POCO类必须是 public 且不能为 sealed

2. 导航属性标记为 virtual (懒加载的机制是 生成新的子类覆盖原来的POCO类)

3. Configuation.LazyLoadingEnabled 为 true

 

假设一个类 User 包含外键 Class

当对这个类集使用 ToList() 将会加载所有 User 到内存, 但不会加载 任何 Class

只有具体引用到某个 User 的 Class 时, 才引发加载.

并且,

根据每次循环都会查询一次数据库

如果不需要这样的设定,

则可以直接使用 User.Include("Class")的方式, 连同 Class 一起加载进内存

 

POCO类

public class Province
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Governor Governor { get; set; }
    public virtual IList<City> Cities { get; set; }
}

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

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

 

测试代码

private static void LazyLoading(DEMODBContext ctx)
{
    //发送一条查询到数据库,查询所有的province
    var list = ctx.Province.ToList();
    foreach (var province in list)
    {
        //每次遍历(用到导航属性时)都发送2条查询,一条查询当前province包含的city和另一条查询当前province的governor
        //如果ctx.Configuration.LazyLoadingEnabled为false或者前者为true,但是导航属性没有标注为virtual,下面的操作都会抛出异常
        Print(province);
    }
}

private static void EagerLoading(DEMODBContext ctx)
{
    var list = ctx.Province.Include("Cities").Include("Governor");
    //发送一条查询到数据库库,查询所有的province并关联city和governor
    //var list = ctx.Province.Include(t => t.Cities).Include(t => t.Governor);
    foreach (var province in list)
    {
        //不管ctx.Configuration.LazyLoadingEnabled为false,还是没有标注导航属性virtual,都不会抛出异常
        Print(province);
    }
}

private static void ExplicitLoading(DEMODBContext ctx)
{
    //发送一条查询到数据库,查询所有的province
    var list = ctx.Province.ToList();
    foreach (var province in list)
    {
        var p = ctx.Entry(province);
        //发送一条查询,查询所有当前province的city
        p.Collection(t => t.Cities).Load();
        //发送一条查询,查询当前province的governor
        p.Reference(t => t.Governor).Load();
        //不管ctx.Configuration.LazyLoadingEnabled为false,还是没有标注导航属性virtual,都不会抛出异常
        Print(province);
    }
}

private static void Print(Province province)
{
    Console.WriteLine("省:【{0}】,市:【{1}】,省长:【{2}】", province.Name, string.Join(",", province.Cities.Select(t => t.Name)), province.Governor.Name);
}

 

posted @ 2016-03-08 16:09  `Laimic  阅读(251)  评论(0)    收藏  举报