EF Core许多不需要的列

问题描述 投票:0回答:1

我正在尝试创建一个有两次多对多关系的模型。

StockItem * - * QualityCheckDefinition

文章* - * QualityCheckDefinition

多对多班:

public class StockItemQualityCheckDefinition
{
    public StockItem StockItem { get; set; }
    public QualityCheckDefinition QualityCheckDefinition { get; set; }

    public int StockItemId { get; set; }
    public int QualityCheckDefinitionId { get; set; }
}

public class ArticleQualityCheckDefinition
{
    public Article Article { get; set; }
    public QualityCheckDefinition QualityCheckDefinition { get; set; }

    public string ArticleId { get; set; }
    public int QualityCheckDefinitionId { get; set; }
}

QualityCheckDefinition类:

public class QualityCheckDefinition : Entity<int>
{
    public List<StockItemQualityCheckDefinition> StockItemQualityCheckDefinitions { get; set; }
    public List<ArticleQualityCheckDefinition> ArticleQualityCheckDefinitions { get; set; }         
}

文章类:

public class Article : Entity<string>
{
    public ICollection<ArticleQualityCheckDefinition> ArticleQualityCheckDefinitions { get; set; }
}

StockItem类:

public class StockItem : Entity<int>
{
    public List<StockItemQualityCheckDefinition> StockItemQualityCheckDefinitions { get; set; }
}

映射:

public class ArticleQualityCheckDefinitionMap : IEntityTypeConfiguration<ArticleQualityCheckDefinition>
{
    public void Configure(EntityTypeBuilder<ArticleQualityCheckDefinition> builder)
    {
        builder.HasKey(x => new { x.ArticleId, x.QualityCheckDefinitionId });

        builder.HasOne(x => x.Article)
               .WithMany(x => x.ArticleQualityCheckDefinitions)
               .HasForeignKey(x => x.ArticleId)
               .HasPrincipalKey(x => x.Id)
               .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne(x => x.QualityCheckDefinition)
               .WithMany(x => x.ArticleQualityCheckDefinitions)
               .HasForeignKey(x => x.QualityCheckDefinitionId)
               .HasPrincipalKey(x => x.Id)
               .OnDelete(DeleteBehavior.Restrict);
    }
}

public class StockItemQualityDefinitionMap : IEntityTypeConfiguration<StockItemQualityCheckDefinition>
{
    public void Configure(EntityTypeBuilder<StockItemQualityCheckDefinition> builder)
    {
        builder.HasKey(x => new { x.StockItemId, x.QualityCheckDefinitionId });

        builder.HasOne(x => x.StockItem)
               .WithMany(x => x.StockItemQualityCheckDefinitions)
               .HasForeignKey(x => x.StockItemId);

        builder.HasOne(x => x.QualityCheckDefinition)
               .WithMany(x => x.StockItemQualityCheckDefinitions)
               .HasForeignKey(x => x.QualityCheckDefinitionId);
    }
}

关系配置正常,它们正在工作。但是,迁移会在QualityCheckDefinition类中创建其他不需要的字段。迁移想要将可空的StockItemIdArticleId添加到QualityCheckDefinition类。

迁移的一部分:

migrationBuilder.CreateTable(
                name: "QualityCheckDefinitions",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    //other properties
                    ArticleId = table.Column<string>(nullable: true),
                    StockItemId = table.Column<int>(nullable: true)
                },

为什么要添加这些不需要的密钥?

PS。我使用的是EF Core 2.2

c# .net-core entity-framework-core ef-migrations
1个回答
0
投票

StockItemArticle的配置映射在哪里?而且我认为你在.HasPrincipalKey()中使用ArticleQualityCheckDefinitionMap的方式是不对的。

Principal Key

如果希望外键引用主键以外的属性,则可以使用Fluent API配置关系的主键属性。您配置为主键的属性将自动设置为备用键。

Your ArticleQualityCheckDefinitionMap

builder.HasOne(x => x.Article)
    .WithMany(x => x.ArticleQualityCheckDefinitions)
    .HasForeignKey(x => x.ArticleId)        // <--
    .HasPrincipalKey(x => x.Id)             // <--
    .OnDelete(DeleteBehavior.Restrict);

根据惯例,.HasForeignKey(x => x.ArticleId)将瞄准Article实体string Id的主键。然后你告诉Entity Framework你不想设置主键的外键。你想通过说Id来定位另一个名为.HasPrincipalKey(x => x.Id)的属性。

咦?他们不一样吗?这就是为什么我认为实体框架感到困惑。由于您没有Article的配置,Entity Framework会尽力为您生成一个主键,称为“ArticleId”?

你可以通过添加配置并在那里删除.HasPrincipalKey()来解决问题。

StockItemConfiguration

using DL.SO.EFCore.Learning.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace DL.SO.EFCore.Learning.Data.Configurations
{
    public class StockItemConfiguration : IEntityTypeConfiguration<StockItem>
    {
        public void Configure(EntityTypeBuilder<StockItem> builder)
        {
            builder.HasKey(x => x.Id);

            builder.ToTable(nameof(StockItem));
        }
    }
}

ArticleConfiguration

using DL.SO.EFCore.Learning.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace DL.SO.EFCore.Learning.Data.Configurations
{
    public class ArticleConfiguration : IEntityTypeConfiguration<Article>
    {
        public void Configure(EntityTypeBuilder<Article> builder)
        {
            builder.HasKey(x => x.Id);

            builder.ToTable(nameof(Article));
        }
    }
}

您可能还需要配置QualityCheckDefinition

QualityCheckDefinitionConfiguration

using DL.SO.EFCore.Learning.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace DL.SO.EFCore.Learning.Data.Configurations
{
    public class QualityCheckDefinitionConfiguration : IEntityTypeConfiguration<QualityCheckDefinition>
    {
        public void Configure(EntityTypeBuilder<QualityCheckDefinition> builder)
        {
            builder.HasKey(x => x.Id);

            builder.ToTable(nameof(QualityCheckDefinition));
        }
    }
}

然后删除.HasPrincipalKey()

ArticleQualityCheckDefinitionConfiguration

using DL.SO.EFCore.Learning.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace DL.SO.EFCore.Learning.Data.Configurations
{
    public class ArticleQualityCheckDefinitionConfiguration : IEntityTypeConfiguration<ArticleQualityCheckDefinition>
    {
        public void Configure(EntityTypeBuilder<ArticleQualityCheckDefinition> builder)
        {
            builder.HasKey(x => new { x.ArticleId, x.QualityCheckDefinitionId });

            builder.HasOne(x => x.Article)
                .WithMany(x => x.ArticleQualityCheckDefinitions)
                .HasForeignKey(x => x.ArticleId);

            builder.HasOne(x => x.QualityCheckDefinition)
                .WithMany(x => x.ArticleQualityCheckDefinitions)
                .HasForeignKey(x => x.QualityCheckDefinitionId);

            builder.ToTable(nameof(ArticleQualityCheckDefinition));
        }
    }
}

那你应该没问题?

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.