实体框架代码优先于同一表上的多对多关系

时间:2019-05-31 16:14:18

标签: c# entity-framework

在这里我有一个有点奇怪的场景,我有一个实体和一个多对多表。下表是这样的:

AssetHeader.cs

[Table("AssetHeader", Schema = "assets")]
public class AssetHeader
{
    public Guid Id { get; set; }

    public virtual ICollection<AssetHeaderEquipment> AssetHeaders { get; set; }

    public virtual ICollection<AssetHeaderEquipment> AssetEquipment { get; set; }
}

AssetHeaderEquipment.cs(多对多)

[Table("AssetHeaderEquipment", Schema = "assets")]
public class AssetHeaderEquipment
{
    [Key, Column(Order = 0)]
    public Guid AssetHeaderId { get; set; }
    [Key, Column(Order = 1)]
    public Guid AssetEquipmentId { get; set; }

    public virtual AssetHeader AssetHeader { get; set; }
    public virtual AssetHeader AssetEquipment { get; set; }

    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }

    [MaxLength(255)]
    public string Comment { get; set; }
}

当我尝试通过代码优先迁移创建数据库时,在SQL中得到以下信息: enter image description here

如何首先获得代码以生成正确的db结构,我很高兴在dbcontext中使用属性或流畅的语言。

2 个答案:

答案 0 :(得分:0)

您可以在业务模型上使用IEntityTypeConfiguration界面并配置外键。

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

public class AssetHeaderEquipment : IEntityTypeConfiguration<AssetHeaderEquipment>
{
    public Guid AssetHeaderId { get; set; }
    public virtual AssetHeader AssetHeader { get; set; }

    public Guid AssetEquipmentId { get; set; }
    public virtual AssetHeader AssetEquipment { get; set; }

    //other properties

    public void Configure(EntityTypeBuilder<AssetHeaderEquipment> builder)
    {
        builder.HasKey(x => new { x.AssetHeaderId, x.AssetEquipmentId });
        builder.HasOne(x => x.AssetHeader).WithMany(x => x.AssetHeaders).HasForeignKey(x => x.AssetHeaderId);
        builder.HasOne(x => x.AssetEquipment).WithMany(x => x.AssetEquipment).HasForeignKey(x => x.AssetEquipmentId);
    }
}

然后在OnModelCreating方法内添加以下行:

builder.ApplyConfiguration(new AssetHeaderEquipment());

答案 1 :(得分:0)

这是EF无法自动配对关系导航属性的情况之一。

通常,它可以使用InverseProperty属性或Has / With流利的API进行解析。但是,由于这种类型的关系始终会带来“多个级联路径”问题,这需要关闭至少一种关系的级联删除,并且只能使用fluent API才能完成,因此除了使用fluent API(对于关系,恕我直言更好。)

最低要求是配置要为其关闭级联删除的关系。一旦这样做,EF通常会做剩下的事情。

例如:

modelBuilder.Entity<AssetHeader>()
    .HasMany(e => e.AssetEquipment)
    .WithRequired(e => e.AssetEquipment)
    .WillCascadeOnDelete(false);

结果:

CreateTable(
    "assets.AssetHeaderEquipment",
    c => new
        {
            AssetHeaderId = c.Guid(nullable: false),
            AssetEquipmentId = c.Guid(nullable: false),
            StartDate = c.DateTime(nullable: false),
            EndDate = c.DateTime(),
            Comment = c.String(maxLength: 255),
        })
    .PrimaryKey(t => new { t.AssetHeaderId, t.AssetEquipmentId })
    .ForeignKey("assets.AssetHeader", t => t.AssetEquipmentId)
    .ForeignKey("assets.AssetHeader", t => t.AssetHeaderId, cascadeDelete: true)
    .Index(t => t.AssetHeaderId)
    .Index(t => t.AssetEquipmentId);

CreateTable(
    "assets.AssetHeader",
    c => new
        {
            Id = c.Guid(nullable: false),
        })
    .PrimaryKey(t => t.Id);