h.alex
h.alex

Reputation: 902

EF check collection initialized state

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?

Upvotes: 0

Views: 1443

Answers (3)

Chris Hermut
Chris Hermut

Reputation: 1758

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

Upvotes: 0

Marc Cals
Marc Cals

Reputation: 2989

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

Upvotes: 1

Brian Deragon
Brian Deragon

Reputation: 2967

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
   }

Upvotes: 1

Related Questions