Michael Edwards
Michael Edwards

Reputation: 6518

Mapping relationships in Entity Framework

I am using Entity Framework and I have two tables, a contact relationship table and a contact table. The relationship is many contact relationships to one contact.

In the code below I am trying to get a Contact Relationship and then get the related Contact, however the code below always returns null for Contact.

    [Test]
    public void Mapping_ContactRelationshipsToContacts()
    {
        //Assign
        Guid id = new Guid("118a0d24-cf9d-e111-802d-005056b4000d");

        //Act            
        var result = _db.ContactRelationships.Where(x => x.Id == id).FirstOrDefault().Contact;

        //Assert
        Assert.IsNotNull(result); 
    }

However if I add a line that goes to the DB first and loads the Contact then the Contact Relationship works:

    [Test]
    public void Mapping_ContactRelationshipsToContacts()
    {
        //Assign
        Guid id = new Guid("118a0d24-cf9d-e111-802d-005056b4000d");

        //Act
        var notUsed = _db.Contacts.Where(x => x.Id ==  new Guid("B2A2AB8C-238E-E111-8BF0-005056B4000D")).FirstOrDefault();
        var result = _db.ContactRelationships.Where(x => x.Id == id).FirstOrDefault().Contact;

        //Assert
        Assert.IsNotNull(result);
    }

Notice that I am not using the new variable, all I am doing is ensuring that it is in the DB. Anyone know what causes this behaviour? My mapping for the relationship is:

        modelBuilder.Entity<ContactRelationship>().HasOptional(x => x.Contact)
         .WithMany(o => o.ContactRelationships).HasForeignKey(x => x.ContactID);

I have checked and the ID values are correct and all the data exists.

Upvotes: 0

Views: 168

Answers (1)

Slauma
Slauma

Reputation: 177153

You must either make your navigation properties virtual to enable lazy loading...

public class ContactRelationship
{
    //...
    public virtual Contact Contact { get; set; }
    //...
}

... or you must eager load the navigation property using Include:

var result = _db.ContactRelationships.Include(cr => cr.Contact)
    .Where(x => x.Id == id).FirstOrDefault().Contact;

Your second code snippet works because the Contact is already attached to the context after loading it from the database and because EF establishes relationships automatically between loaded/attached entities. That's not the case in your first code snippet.

Upvotes: 1

Related Questions