Reputation: 2247
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?
Upvotes: 2
Views: 202
Reputation: 2247
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; }
}
Upvotes: 2
Reputation: 109080
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).
Upvotes: 0
Reputation: 31738
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
Upvotes: 0