有没有办法用 EF Core 映射复杂类型
Is there a way to map complex types with EF Core
EF Core 不支持复杂类型映射。
如果我有一个对象,例如:
public class Entity {
public string StringProp {get; set;}
public SubEntity NestedEntity {get; set;}
}
其中子实体是:
public class SubEntity{
public int IntProp {get; set;}
}
我如何将其映射到具有 StringProp 和 IntProp 列的 table。基本上 table 中的一条记录由 Entity 和 SubEntity 的属性组成。
我试过忽略 SubEntity 并在实体中公开它的属性,但这不起作用,因为当忽略 NestedEntity 时,实体上使用其属性的任何属性都没有值。
除了创建具有复杂类型的所有属性的 class 或重构数据库之外,还有其他选择吗?
我决定使用包含所有相关属性的 class
映射到所有必需的 table 列。
作为解决方法,它工作正常。
将在 EF Core 支持复杂类型时更新。
自 EF Core 2.0 以来,ComplexType 映射现已可用。我知道目前有两种方法可以做到这一点。
通过属性
不指定 Column 属性可能会导致 Entity Framework 在没有迁移的情况下无法将属性映射到现有表中的正确列。
例如,它可能映射到 Address_StreetAddress
using System.ComponentModel.DataAnnotations.Schema;
public class User
{
public int Id { get; set; }
// The complex property we want to use
public Address Address { get; set; }
public string UserName { get; set; }
}
// Lets Entity Framework know this class is a complex type
[ComplexType]
public class Address
{
// Maps the property to the correct column name
[Column("Address")]
public string StreeAddress { get; set; }
[Column("City")]
public string City { get; set; }
[Column("State")]
public string State { get; set; }
[Column("Zip")]
public string ZipCode { get; set; }
}
通过流利 API
不指定 HasColumnName 可能会导致 Entity Framework 在没有迁移的情况下无法将属性映射到现有表中的正确列。
例如,它可能映射到 Address_StreetAddress
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class MyContext: DbContext
{
public DbSet<User> Users { get; set; }
public MyContext(DbContextOptions<MyContext> options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>(table =>
{
// Similar to the table variable above, this allows us to get
// an address variable that we can use to map the complex
// type's properties
table.OwnsOne(
x => x.Address,
address =>
{
address.Property(x => x.City).HasColumnName("City");
address.Property(x => x.State).HasColumnName("State");
address.Property(x => x.StreetAddress).HasColumnName("Address");
address.Property(x => x.SuiteNumber).HasColumnName("SuiteNumber");
address.Property(x => x.ZipCode).HasColumnName("Zip");
});
});
}
}
EF Core 不支持复杂类型映射。
如果我有一个对象,例如:
public class Entity {
public string StringProp {get; set;}
public SubEntity NestedEntity {get; set;}
}
其中子实体是:
public class SubEntity{
public int IntProp {get; set;}
}
我如何将其映射到具有 StringProp 和 IntProp 列的 table。基本上 table 中的一条记录由 Entity 和 SubEntity 的属性组成。
我试过忽略 SubEntity 并在实体中公开它的属性,但这不起作用,因为当忽略 NestedEntity 时,实体上使用其属性的任何属性都没有值。
除了创建具有复杂类型的所有属性的 class 或重构数据库之外,还有其他选择吗?
我决定使用包含所有相关属性的 class 映射到所有必需的 table 列。 作为解决方法,它工作正常。 将在 EF Core 支持复杂类型时更新。
自 EF Core 2.0 以来,ComplexType 映射现已可用。我知道目前有两种方法可以做到这一点。
通过属性
不指定 Column 属性可能会导致 Entity Framework 在没有迁移的情况下无法将属性映射到现有表中的正确列。
例如,它可能映射到 Address_StreetAddress
using System.ComponentModel.DataAnnotations.Schema;
public class User
{
public int Id { get; set; }
// The complex property we want to use
public Address Address { get; set; }
public string UserName { get; set; }
}
// Lets Entity Framework know this class is a complex type
[ComplexType]
public class Address
{
// Maps the property to the correct column name
[Column("Address")]
public string StreeAddress { get; set; }
[Column("City")]
public string City { get; set; }
[Column("State")]
public string State { get; set; }
[Column("Zip")]
public string ZipCode { get; set; }
}
通过流利 API
不指定 HasColumnName 可能会导致 Entity Framework 在没有迁移的情况下无法将属性映射到现有表中的正确列。
例如,它可能映射到 Address_StreetAddress
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class MyContext: DbContext
{
public DbSet<User> Users { get; set; }
public MyContext(DbContextOptions<MyContext> options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>(table =>
{
// Similar to the table variable above, this allows us to get
// an address variable that we can use to map the complex
// type's properties
table.OwnsOne(
x => x.Address,
address =>
{
address.Property(x => x.City).HasColumnName("City");
address.Property(x => x.State).HasColumnName("State");
address.Property(x => x.StreetAddress).HasColumnName("Address");
address.Property(x => x.SuiteNumber).HasColumnName("SuiteNumber");
address.Property(x => x.ZipCode).HasColumnName("Zip");
});
});
}
}