0

Let's assume the following classes:

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);        
    }
}

My question is - is there a way in EF to check the two 'is loaded' states? I want to ensure that the books author and the books collection are not loaded only to be disassociated.

I want to write something like:

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);        
    }
}

Is this possible?

h.alex
  • 902
  • 1
  • 8
  • 31
  • out of interest what do you mean by disassociated ? The fact that a related object is loaded in the context or not doesnt change the association. – phil soady Nov 07 '14 at 19:31

3 Answers3

1

I know you can check to see if the collection is loaded by using the RelationshipManager which will work with any entity that contains a relationship, and implements IEntityWithRelationships.

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

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

Note: You'll have to substitute in your proper foreign key name instead of "FK_Authors_Books".

I believe you can also do the same thing with GetRelatedReference for a single object.

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

   if (result.IsLoaded == false)
   {
       // do something here
   }
Brian Deragon
  • 2,929
  • 24
  • 44
1

In your DBContext you can check if an object it's loaded accessing property Local, for example: DBContext.Book.Local

I think that you would be able to do something like this

public IsLoaded(Book book)
{
    DBContext.Book.Local.Count(b => b.ID == book.ID) > 0;
}
Marc Cals
  • 2,963
  • 4
  • 30
  • 48
0

Keep in mind that I'm not EF expert but maybe it will give you an idea. DbContext.Entry method gives you access to all the information that the DBContext has about an entity. In my understanding you want to know if passed object (as parameter) is already in memory?

Also keep in mind that below method is using 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
            }
        }
     }
}

For navigation properties of type Collection you just use .Collection instead of .Reference.

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

Chris Hermut
  • 1,708
  • 3
  • 17
  • 32
  • DbContext.Entry calls DetectChanges which can take a while (seconds or more). Make sure you disable AutoDetectChangesEnabled before calling it. – Zar Shardan Mar 15 '19 at 15:42