0

I have a DBContext that is initializing through DropCreateDatabaseAlways class. In the Seed method I have this code:

            base.Seed(context);
            var c1 = new Company { Name = "Samsung"};
            var c2 = new Company { Name = "Microsoft"};
            context.Companies.AddRange(new List<Company>{c1,c2 });
            var phones = new List<Phone>
            {
                new Phone("Samsung Galaxy S5", 20000, c1),
                new Phone("Nokia S1243", 200000, c1),
                new Phone("Nokia 930", 10000, c2),
                new Phone("Nokia 890", 8900, c2)

            };
            context.Phones.AddRange(phones);

            context.SaveChanges();

And if iterate through phones now, I see that phone.Company is not null. But when I do this in any other piece of code, phone.Company IS null. What do I do wrong? A simple piece of code with null phone.Company:

using (var db = new MyDataModel())
        {
            var phonesList = db.Phones.ToList();
            foreach (var p in phones)
            {
                System.Console.WriteLine($"Name: {p.Name} 
                Company: {p.Company}"); // Company is null.
            }
        }

I can access Company using Join with Companies on phone.companyId, so Companies table exists in DB.

My DataModel class:

public class MyDataModel : DbContext
{
    public MyDataModel()
        : base("name=MyDataModel")
    {
    }

    static MyDataModel()
    {
        Database.SetInitializer(new MyContextInializer());
    }

    public DbSet<Company> Companies { get; set; }
    public DbSet<Phone> Phones { get; set; }
}

My Phone class:

namespace DataContext
{


public class Phone
    {
        public Phone()
        {

        }
        public Phone(string name, int price, Company company)
        {
            Name = name;
            Price = price;
            Company = company;
        }

        public int Id { get; set; }

        public string Name { get; set; }

        public int Price { get; set; }

        public int CompanyId { get; set; }

        public Company Company { get; set; }

    }
}
Immorality
  • 2,164
  • 2
  • 12
  • 24
Victor Gorban
  • 1,159
  • 16
  • 30

2 Answers2

1

If you want to automagically load the companies when you load a phone, you need to add the virtual keyword before the Company property.

public class Phone { 

    public Phone() {

    }
    public Phone(string name, int price, Company company)
    {
        Name = name;
        Price = price;
        Company = company;
    }

    public int Id { get; set; }

    public string Name { get; set; }

    public int Price { get; set; }

    public int CompanyId { get; set; }

    public virtual Company Company { get; set; }

}

This tells entity framework to automatically load the linked company whenever you retrieve a phone from the database.

Alternatively you can use eager loading when performing a query on phones.

var phones = MyDataModel.Phones.Include(x => x.Company).ToList();
Immorality
  • 2,164
  • 2
  • 12
  • 24
0

In addition to the cool answer from Immorality, I'll place here these links:

  1. Virtual properties

  2. MSDN - Loading related data strategies

Victor Gorban
  • 1,159
  • 16
  • 30