Entity Framework Code First navigational propertie

2019-07-16 03:56发布

问题:

For a program I'm using EF code first for the first time. In the past I used linq to SQL en EF DbFirst. When retreiving the main record'I'm unable to load the subrecords using the navigational properties. I get an empty subrecord with all record-fields are 0 or null.

When I want to apply eager loading. the .Include(x=>x.......) isn't showing my navigationals.

I have set up the following classes:

public Record()
    {
        Shipping = new ShippingData();
        Delivery = new DeliveryData();
        Items = new List<Item>();
        ImportDate = DateTime.Now;
    }

    [Key]
    public int RecordId { get; set; }
    public int ShippingId { get; set; }
    public int DeliveryId { get; set; }
    public DateTime ImportDate { get; set; }

    public virtual ShippingData Shipping { get; set; }
    public virtual DeliveryData Delivery { get; set; }
    public virtual List<Item> Items { get; set; }
    public virtual Collecting CollectingOrder { get; set; }

with the following context:

public class TweemansContext : DbContext
{
    public TweemansContext()
        : base("xxxx")
    {
    }

    public DbSet<Add.Record> Records { get; set; }
    public DbSet<Add.ShippingData> Shipping { get; set; }
    public DbSet<Add.DeliveryData> Delivery { get; set; }
    public DbSet<Add.Item> ProductItems { get; set; }
    public DbSet<Add.Kolli> Kolli { get; set; }
    public DbSet<Add.Collecting> CollectingOrders { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Record>().HasRequired(s => s.Shipping)
                    .WithMany()
                    .HasForeignKey(s => s.ShippingId);
        modelBuilder.Entity<Record>().HasRequired(d => d.Delivery)
                    .WithMany()
                    .HasForeignKey(d => d.DeliveryId);
        modelBuilder.Entity<Record>().HasOptional(c => c.CollectingOrder)
                    .WithOptionalDependent(a => a.Record).Map(p => p.MapKey("CollectionID"));
    }
}

the delivery class is a public class as wel as follows:

    public class DeliveryData
{
    [Key]
    public int DeliveryId { get; set; }
    public virtual Record Record { get; set; }

    ....lots of public properties

now when I try to use lazy loading all my properties of the delivery class are null using the following code:

using (TweemansContext context = new TweemansContext())
        {
            var imported = (from record in context.Records
                            where record.ImportDate.Year == date.Year && record.ImportDate.Month == date.Month && record.ImportDate.Day == date.Day
                            select record).ToList();

            foreach (var Record in imported)
            {
                string email;
                string telnr;
                CustomerService service = new CustomerService(connectionString);
                **string servicenr = Record.Delivery.AccountNumber.Substring(2, 8);**
                service.GetUserData(servicenr, out email, out telnr);
                Record.Delivery.Email = email;
                Record.Delivery.TelephoneNbr = telnr;
            }
            context.SaveChanges();
        }

on the rows with the ** my debugger is telling me that delivery exists but all of it's properties are null.

When wanting to apply an include as follows the .include isn't showing my navigation:

    var imported = (from record in context.Records.Include(x=>x.)
                            where 
                               record.ImportDate.Year == date.Year 
                               && record.ImportDate.Month == date.Month
                               && record.ImportDate.Day == date.Day
                            select record).ToList();

What am I doing wrong, or which part have i misuderstood??

回答1:

You must remove the initialization of the navigation references from the Record constructor, the initialization of the empty navigation collection is OK:

Shipping = new ShippingData(); // remove this line
Delivery = new DeliveryData(); // remove this line

Essentially these lines "overwrite" the loaded data with values that the constructors of ShippingData and DeliveryData set, probably the default values 0 and null.

Side note about your remark "the .Include(x=>x.......) isn't showing my navigationals". You need to put using System.Data.Entity; at the beginning of your code file to make the Include extension method available that takes a lambda expression as parameter.



回答2:

When your debug stop there you should be getting a proxy class on Delivery. if you are no getting this you should enable lazy load on your context. You can check here how to enable lazy load.

If you don't want to enable lazy load you should use Include in your query to include the Delivery information. Here you can have some info how to use include.