【问题标题】:EF check collection initialized stateEF 检查集合初始化状态
【发布时间】:2014-12-23 08:13:39
【问题描述】:

让我们假设以下类:

public class Author
{
    public virtual string Name { get; set; }
    public virtual List<Book> Books { get; set; }
} 

public class Book
{
    public virtual string Name { get; set; }
    public virtual Author Author { get; set; }
}

public class Controller
{
    public void DeleteBook(Book book)
    {
        var author = book.Author; //first check if it is loaded, not to invoke lazy loading?
        author.Books.Remove(book) //check if the books collection is loaded?
        book.Author = null;

        Context.Set<Book>().Remove(book);        
    }
}

我的问题是 - EF 有没有办法检查两个“已加载”状态? 我想确保书籍作者和书籍收藏不会被加载只是为了解除关联。

我想写这样的东西:

public class Controller
{
    public void DeleteBook(Book book)
    {
        if (EF.IsLoaded(book.Author)) //has it been (lazy) loaded / initialized?
        {
             if (EF.IsLoaded(book.Author.Books) //has it been (lazy) loaded / initialized?
             {
                 book.Author.Books.Remove(book);
             }
             book.Author = null;
        }
        Context.Set<Book>().Remove(book);        
    }
}

这可能吗?

【问题讨论】:

  • 出于兴趣 你所说的不相关是什么意思?相关对象是否已加载到上下文中这一事实不会改变关联。

标签: c# entity-framework collections lazy-loading proxy-classes


【解决方案1】:

我知道您可以使用RelationshipManager 检查集合是否已加载,该RelationshipManager 将适用于任何包含关系的实体,并实现IEntityWithRelationships

 var result = ((IEntityWithRelationships)(author)).RelationshipManager
       .GetRelatedCollection<Books>("FK_Authors_Books", "Books");

   if (result.IsLoaded == false)
   {
       // do something here
   }

注意:您必须用正确的外键名称代替“FK_Authors_Books”。

我相信您也可以使用 GetRelatedReference 对单个对象执行相同的操作。

 var result = ((IEntityWithRelationships)(book)).RelationshipManager
       .GetRelatedReference<Author>("FK_Books_Author", "Author");

   if (result.IsLoaded == false)
   {
       // do something here
   }

【讨论】:

    【解决方案2】:

    在您的 DBContext 中,您可以检查是否加载了访问属性 Local 的对象,例如:DBContext.Book.Local

    我认为你可以做这样的事情

    public IsLoaded(Book book)
    {
        DBContext.Book.Local.Count(b => b.ID == book.ID) > 0;
    }
    

    【讨论】:

      【解决方案3】:

      请记住,我不是 EF 专家,但也许它会给你一个想法。 DbContext.Entry 方法使您可以访问 DBContext 拥有的有关实体的所有信息。据我了解,您想知道传递的对象(作为参数)是否已经在内存中?

      另外请记住,下面的方法是使用explicit loading

      public class Controller
      {
          public void DeleteBook(Book book)
          {
              // assuming that you're working on context directly and need to dispose it
              using (var context = new YourContext())
              {
                  var entry = context.Entry(book);
                  // Will tell you if Author navigation property is loaded
                  bool isLoaded = entry.Reference(x => x.Author).IsLoaded();
      
                  if (isLoaded != false)
                  {
                      // do when Author navigation property is loaded
                  }
                  else
                  {
                      // do when Author navigation property is not loaded
                  }
              }
           }
      }
      

      对于 Collection 类型的导航属性,您只需使用 .Collection 而不是 .Reference。

      http://msdn.microsoft.com/en-us/library/system.data.objects.dataclasses.relatedend.isloaded(v=vs.110).aspx

      【讨论】:

      • DbContext.Entry 调用 DetectChanges 可能需要一段时间(几秒钟或更长时间)。确保在调用它之前禁用 AutoDetectChangesEnabled。
      猜你喜欢
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 2021-10-13
      • 2019-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多