Mac Luc
Mac Luc

Reputation: 1001

How to setup a proper navigation property using Entity Framework?

I'm trying to create a .NET MVC website, and I'm having some trouble with loading and saving related tables in my database through entity framework.

1) When i try to access a related entity from one table, my navigation property seem to be empty even though it shouldnt?

public class Table1 {
    public int Table1ID { get; set; }
    public string Name { get; set; }
    [ForeignKey("Table2")]
    public int Table2ID { get; set; }
    [ForeignKey("Table2ID")]
    public virtual Table2 Table2 { get; set; }
}

public class Table2 {
    public int Table2ID { get; set; }
    public string Name { get; set; }
    public virtual Table1 Table1 { get; set; }
}

I have my mapping like this in my EF context class:

public class EFDbContext : DbContext {
    public DbSet<Table1> Table1 { get; set; }
    public DbSet<Table2> Table2 { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Table2>().HasOptional(u => u.Table1).WithRequired().WillCascadeOnDelete(true);
    }
}

In my controller i fetch the wanted Table2 instance and send it to my View:

public ViewResult Edit(int productId) {
    Table2 Table2Instance = repository.Table2.FirstOrDefault(p => p.Table2ID == productId);
    return View(Table2Instance);
}

In my view i need to do an action depending if the Table2Instance has a relation to Table1 or not, which i try to do like this:

@model Entities.Table2

@if (Model.Table1 == null && Model.Table2ID != 0){
    //Do this
}else if (Model.Table1 != null && Model.Table2ID != 0) {
    //Do that
}

But it seems like my navigation property doesnt work properly, since it will always show Model.Table1 as null even if the database has a relation. How should i set up this navigation property right?

2) When i try to save a new Table1 property with context.Table1.Add(Table1Instance) and then context.SaveChanges() i get an error, because it tries to save the Table1ID as 0 everytime and does not increment?

Upvotes: 0

Views: 131

Answers (2)

Erik Philips
Erik Philips

Reputation: 54638

because it tries to save the Table1ID as 0 everytime and does not increment?

You need to include setting a column as an Identity column:

modelBuilder.Entity<Table2>()
  .HasOptional(u => u.Table1)
  .WithRequired()
  .WillCascadeOnDelete(true);

modelBuilder.Entity<Table2>()
  .Property(x => x.Table2ID )
  .StoreGeneratedPattern = StoreGeneratedPattern.Identity;

Upvotes: 0

JotaBe
JotaBe

Reputation: 39055

The related navigation properties are not read by default. To read them you can use:

  • lazy loading (i.e. accessing the property when LazyLoading is enabled)
  • eager loading (i.e. using Include)
  • explicit loading (it's a bitmore complicated)

In your case, the more appropriate solution is eager loading, which is done like this:

Table2 Table2Instance = repository
  .Table2
  .Include(t2 => t2.Table1) // add this to your query
  .FirstOrDefault(p => p.Table2ID == productId);

As to the second question, you should show more code. You must be aware that in a layered application, when your entity gets out of the DbContext you have to attach it back, and set the entity status before calling SaveChanges.

Upvotes: 2

Related Questions