简体   繁体   中英

Entity Framework - Multiple 1 to 0..1 relationships using the same Key

I've read as many posts as I can on this topic but none of the solutions I have tried seem to work. I have an existing database and created a new Code First From Existing Database project.

I have a base table called Thing. Every object has a record in this table using Id as the Unique Primary Key. Each other object inherits from this but they use the same Id in the child tables without using a new Identity column in the sub tables. Effectively giving each 'Thing' a unique Id:

public class Thing
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Car
{
    public int Id { get; set; }
    //other properties
}

public class Person
{
    public int Id { get; set; }
    //other properties
}

public class Color
{
    public int Id { get; set; }
    //other properties
}

Every new record first creates an item in 'Thing' and then using that Id value creates a new record in its respective table, creating multiple 1 to 0..1 relationships where the Id field on the derived tables is also the FK to Thing.

Thing 1 to 0..1 Car

Thing 1 to 0..1 Person

Thing 1 to 0..1 Color

and so on

I have tried many different Data Annotation and Fluent API combinations but it always comes back to the same error:

'Unable to retrieve metadata for Model.Car'. Unable to determine the principal end of association between the types 'Model.Thing' and 'Model.Car'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.'

I did manage to get past this error by using virtual with the inverse annotation and setting the Id field to be Key and ForeignKey, but then the message jumps to Person. If you then set it up the same as Car the message reverts back to Car.

It seems I could go back and create a normal Foreign Key to each child table, but that is a lot of work and I am sure it is possible to get this working somehow. Preferably using fluent API.

If you are going to use Data Annotations, you need to declare the PK of the dependent entity as FK too:

public class Thing
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Car Car{get;set;}
}

public class Car
{
    [Key,ForeignKey("Thing")]
    public int ThingId { get; set; }
    //other properties

    public virtual Thing Thing{get;set;}
}

And if you are going to use Fluent Api (remove the attributes from your model), the configuration would be like this:

modelBuilder.Entity<Car>().HasRequired(c=>c.Thing).WithOptional(t=>t.Thing);

Based on the multiplicity that is specified, it only makes sense for Thing to be the principal and Car to be the dependent, since a Thing can exist without a Car but a Car must have a Thing .

As you can see you don't need to specify that ThingId is the FK of this relationship.This is because of Entity Framework's requirement that the primary key of the dependent be used as the foreign key. Since there is no choice, Code First will just infer this for you.

Update

Reading again your question I think you are trying to create a hierarchy. In that case you could use the Table per Type (TPT) approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM