Complex Type requires primary key

2019-08-21 18:47发布

问题:

I have an object that contains an attribute with the type of another object, which I want to treat as Complex Type.

public class Location : IModule
{
    public string Id { get; set; }
    public Coordinate Coordinate { get; set; }
}

[ComplexType]
public class Coordinate
{
    public string Latitude { get; set; }
    public string Longitude { get; set; }
}

While adding a migration, I ran into the problem that a primary key is required (exactly what I want to prevent).

The entity type Coordinate requires a primary key to be defined.

EDIT

For performance reasons I want the properties being stored as Coordinate_Latitude and Coordinate_Longitute instead of having a reference to another table.

回答1:

You need to define a key, to make it works. This is how the Entity Framework works, Entity Framework needs to know the key to keep track on the object when you make an update or delete operation. Just if you don't want to manually insert it, you can declare it as an identity column to auto increment it. Something like this:

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CoordinateKey { get; set; }

Or with Fluent-API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Coordinate>().HasKey(u => u.CoordinateKey);
    modelBuilder.Entity<Coordinate>().Property(c => c.CoordinateKey)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}

Edit: It seems you want to treat the Coordinate class as a not mapped class. You can use NotMapped attribute. Have a look at the following question to know how:

Entity Framework code first: How to ignore classes



回答2:

Based on this question (How do I implement a simple "complex type" in Entity Framework Core 2/C#?), I found the answer: Owned entity types do the trick.

public class Location : IModule
{
    public string Id { get; set; }
    public Coordinate Coordinate { get; set; }
}

[Owned]
public class Coordinate
{
    public string Latitude { get; set; }
    public string Longitude { get; set; }
}

This creates a table containt the attributes Id, Coordinate_Latitued, Coordinate_Longitude.