【问题标题】:Port existing code first models, and fluent aPI configuration from Entity Framework 6 to Entity Framework Core 2.0将现有的代码优先模型和流畅的 API 配置从 Entity Framework 6 移植到 Entity Framework Core 2.0
【发布时间】:2018-07-29 07:27:28
【问题描述】:

假设在使用 Ef 6 的应用程序中,我有以下模型和 fluentapi 配置,这些配置定义了车主与他拥有的汽车之间的关系。 Car 和 CarOwner 的关系是 1 比 0 或 1,而 CarOwner 和 Car 的关系是 1 比 0 或多;

public class Car
{
    public int Id { get; set; }
    public string ChasisNumber { get; set; }
    public string EngineNumber { get; set; }

    public CarOwner CarOwner { get; set; }
}

public class CarOwner
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public IList<Car> Cars {get; set;}
}

对应的fluent api配置如下图

public class CarConfiguration : EntityTypeConfiguration<Car>
{
    HasKey(a => a.Id);
    Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
    HasOptional(x => x.CarOwner).WithMany(x => x.Cars).Map(x => x.MapKey("CarOwner_Id"));
}

public class CarOwnerConfiguration : EntityTypeConfiguration<CarOwner>
{
    HasKey(a => a.Id);
    Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
    HasMany(a => a.Cars).WithOptional(a => a.CarOwner);
}

在 EF Core 2.0 中,Car 模型发生了变化,因为需要将模型中的 CarOwner 外键指定为可为空的整数属性,但我不想这样做。

public class Car
{
    public int Id { get; set; }
    public string ChasisNumber { get; set; }
    public string EngineNumber { get; set; }

    public int? CarOwnerId { get;set; }
    public CarOwner CarOwner { get; set; }
}

有没有办法可以防止将 CarOwnerId 添加为 Car 实体中的引用键?我想确保我的模型与 Entity Framework 6 中的模型保持一致。我不想对我的模型进行任何更改。我希望在 fluent api 配置文件中进行所有必要的更改。

【问题讨论】:

    标签: c# .net entity-framework-6 ef-code-first ef-core-2.0


    【解决方案1】:

    在 EF Core 2.0 中,Car 模型发生更改,因为需要将模型中的 CarOwner 外键指定为可为空的整数属性

    当然没有必要这样做。事实上,EF Core 让您可以更好地控制shadow properties。只是默认的 FK 名称约定不同,因此为了保留 EF6 名称,您必须使用 fluent API 显式配置它们。

    这是原始模型的等效 EF Core 配置(Car 内没有 public int? CarOwnerId { get;set; }):

    public class CarConfiguration : IEntityTypeConfiguration<Car>
    {
        public void Configure(EntityTypeBuilder<Car> builder)
        {
            builder.HasKey(a => a.Id);
            builder.Property(a => a.Id).ValueGeneratedOnAdd().IsRequired();
            builder.HasOne(x => x.CarOwner)
                .WithMany(x => x.Cars)
                .HasForeignKey("CarOwner_Id") // <--
                .IsRequired(false);
        }
    }
    
    public class CarOwnerConfiguration : IEntityTypeConfiguration<CarOwner>
    {
        public void Configure(EntityTypeBuilder<CarOwner> builder)
        {
            builder.HasKey(a => a.Id);
            builder.Property(a => a.Id).ValueGeneratedOnAdd().IsRequired();
        }
    }
    

    请注意,大多数 fluent 配置都是多余的,可以省略,因为它们是 EF 的常规默认设置。此外,关系配置应该放在一个位置以避免设置冲突 - 关系总是有两个端点,因此从逻辑上讲,它不是两个实体中任何一个实体的一部分(不适合实体类型配置分离)。

    实现相同映射的最小流利配置是这样的(完全不使用实体类型配置):

    modelBuilder.Entity<Car>()
        .HasOne(x => x.CarOwner)
        .WithMany(x => x.Cars)
        .HasForeignKey("CarOwner_Id");
    

    【讨论】:

    • 感谢您抽出时间来回答。你的回答很有帮助
    猜你喜欢
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多