2

I have two object Classes

 class Person
{

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set;}
    public DateTime BirthDate { get; set; }
    public bool IsMale { get; set; }
    public byte[] Image { get; set; }
    public byte[] RowVersion { get; set; }
    public virtual Person Parent { get; set; }
    public virtual ICollection<PhoneNumber> PhoneNumber { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
    public virtual  PersonInfo PersonInfo { get; set; }

}

and :

class PhoneNumber
{

    public enum PhoneType
    { Work, Mobile, Home };

    public int id { get; set; }
    public string phoneNumber { get; set; }
    public PhoneType phoneType { get; set; }
    public virtual Person Person { get; set; }
}

I added "virtual" keyword to my navigation properties to enable LazyLoading, then i added some codes for getting list of persons:

using (var newContext = new MyDbContext())

    {
        var selectedPerson = newContext.Persons.ToList();  
    }

But, when i run my project, i get the PhoneNumber being null! I thought if i add "virtual" keyword to my navigation properties then i get the PhoneNumber as well.. I got it all wrong?

5
  • have you turned lazy loading on? Commented Jan 22, 2014 at 6:31
  • I think it is enough if i add "virtual" keyword to my navigation keywords like: person and phone number !!! Commented Jan 22, 2014 at 6:34
  • Yes, you think so but it's not. Commented Jan 22, 2014 at 6:36
  • Make sure you have newContext.Configuration.LazyLoadingEnabled equal to true Commented Jan 22, 2014 at 6:38
  • @SergeyBerezovskiy, i did it, but its not work!! Commented Jan 22, 2014 at 6:42

3 Answers 3

2

I found the solution, i should added public modifier to my object classes so :

 Public class Person
  {

     public int Id { get; set; }
     public string FirstName { get; set; }
     public string LastName { get; set;}
     public DateTime BirthDate { get; set; }
     public bool IsMale { get; set; }
     public byte[] Image { get; set; }
     public byte[] RowVersion { get; set; }
     public virtual Person Parent { get; set; }
     public virtual ICollection<PhoneNumber> PhoneNumber { get; set; }
     public virtual ICollection<Address> Addresses { get; set; }
     public virtual  PersonInfo PersonInfo { get; set; }

  }

and :

 Public class PhoneNumber
  {

    public enum PhoneType
    { Work, Mobile, Home };

     public int id { get; set; }
     public string phoneNumber { get; set; }
     public PhoneType phoneType { get; set; }
     public virtual Person Person { get; set; }
  }
Sign up to request clarification or add additional context in comments.

Comments

0

First: I don't know if that makes any difference but I have configured my navigation properties as List<T> and lazy loading works.

Maybe with ICollection<T> EF does not initialize these collections because it does not know which concrete list type to use (just a guess)

 public virtual List<PhoneNumber> PhoneNumbers { get; set; }

Second: By default you don't have to explicitly configure something, it should work out of the box. Anyway, make sure you don't disable LazyLoadingEnabled and ProxyCreationEnabled

Third: Enum Data types are supported since EF5 with Framework 4.5 (if you still run Framework 4.0 you should set it phoneType to int

2 Comments

Thanks.. are Lazy Loading and Proxy enabled by default in EntityFramework5?
Yes, I think so. I never explicitly set those values in my config and it works. You can check that with var person = context.Persons.Find(1); Now check person.GetType().Name - it should be something like System.Data.Entity.DynamicProxies.Person_ABCBE0D1022D01EB84B81873D49DEECC60879FC4152BB115215C3EC16FB8003A and person.PhoneNumbers should be an empty list even if no related records are available.
0

Your code

using (var newContext = new MyDbContext())
{
    var selectedPerson = newContext.Persons.ToList();  
}

will never load PhoneNumbers (or any navigation property) because you don't Include them. And after the statement has run the context is disposed, so any lazy loading attempt will throw an exception.

So (assuming that you didn't disable lazy loading in the context by setting either LazyLoadingEnabled or ProxyCreationEnabled = false.) you should either include the PhoneNumbers

var selectedPerson = newContext.Persons.Include(p => p.PhoneNumbers).ToList();

or address a person's PhoneNumbers collection within the lifespan of the context. (Which will execute additional SQL queries).

2 Comments

I think it is enough if i add "virtual" to my navigation property, in your code, you demand something like this : Person Join with Phone, so you explicitly do the loading and it is not Lazy loading.
No, that's not lazy, but I also indicated the conditions for lazy loading to succeed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.