DMac the Destroyer
DMac the Destroyer

Reputation: 5290

EF Code First unidirectional One-To-Many with Data Annotations Conflicts with other Foreign Key

Say I have the following POCO classes:

public class AuditableModel
{
  public int ID { get; set; }

  public int? SomeOtherModelID { get; set; }

  [ForeignKey("SomeOtherModelID")]
  public SomeOtherModel SomeOtherModel { get; set; }

  public int LastUpdateBy { get; set; }

  [ForeignKey("LastUpdateBy")]
  public AuditableModel LastUpdateByModel { get; set; }
}

public class SomeOtherModel
{
  public int ID { get; set; }

  public int LastUpdateBy { get; set; }

  [ForeignKey("LastUpdateBy")]
  public AuditableModel LastUpdateByModel { get; set; }
}

In this example, I have a foreign key on AuditableModel pointing to SomeOtherModel and a foreign key on SomeOtherModel pointing to AuditableModel, both are a one-to-many, both should be unidirectional.

When trying to query my AuditableModel class, I get the "Unable to determine the principal end of an association" exception. There are two ways I've found to get around this exception:

  1. Remove the SomeOtherModelID and SomeOtherModel properties on AuditableModel
  2. Code the relationship on SomeOtherModel in the DbContext's OnModelCreating method using the fluent API.

I'll implement using the fluent API, but would have rather done it completely via conventions and data annotations. Is there a way, or am I stuck defining these relationships via configuration?

Upvotes: 2

Views: 907

Answers (2)

Slauma
Slauma

Reputation: 177163

I agree with @Eranga. This only works with Fluent API. What exactly is going wrong here is that conventions detect a single navigation property on AuditableModel refering to SomeOtherModel and a single navigation property on SomeOtherModel refering to AuditableModel. Mapping conventions try to create a one-to-one relationship (because neither of the navigation properties is a collection) between the entities. Because it's not clear what's the principal and what the dependent you get this exception.

There is no data annotation attribute to resolve this problem, i.e. to tell EF that actually two relationsships should be created with a not-exposed many-side on each relationship. You can only configure this in Fluent API (using the WithMany() overload without a parameter).

Upvotes: 1

Eranga
Eranga

Reputation: 32447

Removing the SomeOtherModelID on AuditableModel may not be an option depending on your domain model.

Attribute based/Convention based configuration has limitations. So in this case you will have to fallback to Fluent API because the relationship inferred by conventions is not what you need.

Upvotes: 1

Related Questions