实体框架中的延迟加载问题

时间:2011-04-30 12:13:11

标签: entity-framework lazy-loading

我在1:n关系中有两个实体:链接,类别。首先,我得到所有类别和链接,并将它们列入清单。接下来,我手动填充每个类别的链接,但category.Links.Add(link)连接到db并再次获取链接,它会导致结果中出现双重数据。我知道这个动作是因为延迟加载。延迟加载是真的,我不想禁用它。如何在不连接到db的情况下手动填充每个类别的链接? 请不要提供Eager加载或消除懒惰负载。

        var categories = categoryRepository.GetCategories().ToList();
        var allLinks = linkRepository.GetLinks().ToList();

        foreach (var category in categories)
        {
            var links = allLinks.Where(l => l.CategoryID == category.CategoryID);

            foreach (var link in links)
            {
                category.Links.Add(link);
            }
        }

1 个答案:

答案 0 :(得分:1)

即使您提到您不想关闭延迟加载我坚持要这样做,因为当您第一次访问导航属性时,将始终触发延迟加载。避免这种情况的唯一方法是:

  • 关闭延迟加载。缺点是您必须关闭延迟加载以进行类别的整个处理。因为一旦打开它,它将在下次访问该属性时立即重新加载Links。原因是用于处理EntityCollection的{​​{1}}具有属性Links,该属性为false(除非通过调用IsLoaded,否则无法修改)。
  • Load集合中删除virtual个关键字。这将禁止仅通过动态代理包装Links,因此不允许延迟加载。它会更有趣,因为加载中唯一需要的代码应该是前两行 - 在第二次查询执行期间,链接将自动填充到类别中。这里的问题是从自动生成的实体中删除虚拟关键字很难(必须硬编码到T4模板)或者您必须使用自己的实体。
  • 通过将Category属性中的EntityCollection替换为另一个集合,以某种方式欺骗EF。这并不容易,因为您不能只将新集合分配给Links - 动态代理将抛出Links。您必须创建实体的第二个部分部分并添加一些代码,这些代码将直接修改保存集合的私有字段(绕过属性)。即使这样的方法也会产生一些不良后果。默认代码使用一些修正等。

关闭延迟加载不会破坏您的功能 - 实际上EF通常在内部执行此操作。你只需要这样做:

InvalidOperationException