繁体   English   中英

实体框架核心 - 使用Npgsql提供程序迁移失败

[英]Entity Framework Core - Failed migration with Npgsql provider

尝试使用Entity Framework Core 2.0.1和提供程序npgsql 2.0.1从其模型创建数据库时出错。

错误描述是:

“约束«FK_PiezasStockExterno_ContenedoresDocumentos_IdContenedorDocume»关系«PiezasStockExterno»已经存在”。

我没有调用Database.EnsureCreated()因为我知道它在迁移时会引起麻烦,并且数据库在被丢弃之前所以我确保它不存在。 它使用以下命令或调用Database.EnsureCreated()。 什么可能是真正的问题?

错误脚本:

CREATE TABLE "public"."PiezasStockExterno" 
(    
"Id" serial NOT NULL,   
"IdContenedorDocumentosPieza" int4 NULL,    
"IdContenedorDocumentosVehiculo" int4 NULL,

CONSTRAINT "PK_PiezasStockExterno" PRIMARY KEY ("Id"),    
CONSTRAINT "FK_PiezasStockExterno_ContenedoresDocumentos_IdContenedorDocumentosPieza" 
    FOREIGN KEY ("IdContenedorDocumentosPieza") 
    REFERENCES "public"."ContenedoresDocumentos" ("Id") ON DELETE RESTRICT,    
CONSTRAINT "FK_PiezasStockExterno_ContenedoresDocumentos_IdContenedorDocumentosVehiculo" 
    FOREIGN KEY ("IdContenedorDocumentosVehiculo") 
    REFERENCES "public"."ContenedoresDocumentos" ("Id") ON DELETE RESTRICT
)

楷模:

[Table("PiezasStockExterno", Schema = "public")]
public class PiezaStockExterno
{

    [Key]
    public int Id { get; set; }

    public int? IdContenedorDocumentosPieza { get; set; }

    [ForeignKey("IdContenedorDocumentosPieza")]
    public virtual ContenedorDocumentos ContenedorDocumentosPieza { get; set; }

    public int? IdContenedorDocumentosVehiculo { get; set; }

    [ForeignKey("IdContenedorDocumentosVehiculo")]
    public virtual ContenedorDocumentos ContenedorDocumentosVehiculo { get; set; }

}

[Table("ContenedoresDocumentos", Schema = "public")]
public class ContenedorDocumentos
{

    [Key]
    public int Id { get; set; }

    [InverseProperty("ContenedorDocumentos")]
    public IList<Imagen> Imagenes { get; set; }

    [InverseProperty("ContenedorDocumentos")]
    public IList<Foto> Fotos { get; set; }

    [InverseProperty("ContenedorDocumentos")]
    public IList<Documento> Documentos { get; set; }

    [InverseProperty("ContenedorDocumentos")]
    public IList<Video> Videos { get; set; }

}

语境:

public NContext(DbContextOptions<NContext> options) : base(options)
{

}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    optionsBuilder.UseNpgsql(ConnectionString, b => b.MigrationsAssembly("WebAPI"));
    optionsBuilder.EnableSensitiveDataLogging();
    base.OnConfiguring(optionsBuilder);
}

WebAPI项目中的Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddEntityFrameworkNpgsql().AddDbContext<Infrastructure.Data.NContext>();       

    services.AddMvc()
        .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()) 
        .AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

    AutoMapperConfig.Initialize();
}

命令:

dotnet ef migrations add InitialMigration
dotnet ef database update

OR

Database.EnsureCreated()

InitialMigration.cs:

    migrationBuilder.CreateTable(
            name: "PiezasStockExterno",
            schema: "public",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),                    
                IdContenedorDocumentosPieza = table.Column<int>(nullable: true),
                IdContenedorDocumentosVehiculo = table.Column<int>(nullable: true)                    
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_PiezasStockExterno", x => x.Id);
                table.ForeignKey(
                    name: "FK_PiezasStockExterno_ContenedoresDocumentos_IdContenedorDocumentosPieza",
                    column: x => x.IdContenedorDocumentosPieza,
                    principalSchema: "public",
                    principalTable: "ContenedoresDocumentos",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_PiezasStockExterno_ContenedoresDocumentos_IdContenedorDocumentosVehiculo",
                    column: x => x.IdContenedorDocumentosVehiculo,
                    principalSchema: "public",
                    principalTable: "ContenedoresDocumentos",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

你绝对会使用FK约束名称命中63字节PostgreSQL最大标识符长度 ,这在截断后变为一个相同,因此混淆已经存在错误(尽管可以看出该名称被截断)。

由于目前只能使用Fluent API指定FK约束名称,因此需要覆盖OnModelCreating并添加以下代码(使用对您有意义且不超过63个字符的任何名称):

modelBuilder.Entity<PiezaStockExterno>()
    .HasOne(e => e.ContenedorDocumentosPieza)
    .WithMany()
    .HasConstraintName("FK_PiezasStockExterno_IdContenedorDocumentosPieza");

modelBuilder.Entity<PiezaStockExterno>()
    .HasOne(e => e.ContenedorDocumentosVehiculo)
    .WithMany()
    .HasConstraintName("FK_PiezasStockExterno_IdContenedorDocumentosVehiculo");

如果您添加逆集合导航属性,请不要忘记更新相应的WithMany调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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