简体   繁体   English

EF Core多对多不需要的列

[英]EF Core many to many unwanted columns

I am trying to create a model which has two time many to many relation. 我正在尝试创建一个具有两次多对多关系的模型。

StockItem * - * QualityCheckDefinition StockItem *-* QualityCheckDefinition

Article * - * QualityCheckDefinition 文章*-* QualityCheckDefinition

Many to many classes: 多对多类:

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 class: QualityCheckDefinition类:

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

Article class: 文章类别:

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

StockItem class: StockItem类:

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

The mappings: 映射:

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);
    }
}

The relationships are configured fine and they are working. 关系配置良好,并且可以正常工作。 However migration creates additional unnesesary fields inside QualityCheckDefinition class. 但是,迁移会在QualityCheckDefinition类内创建其他不必要的字段。 Migration wants to add both nullable StockItemId and ArticleId into QualityCheckDefinition class. 迁移希望将可为空的StockItemIdArticleId添加到QualityCheckDefinition类中。

There is part of migration: 有一部分迁移:

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)
                },

Why does it add these unwanted keys? 为什么要添加这些不需要的密钥?

PS. PS。 I am using EF Core 2.2 我正在使用EF Core 2.2

Where is your configuration mapping for StockItem and Article ? StockItemArticle配置映射在哪里? And I think the way you used .HasPrincipalKey() inside ArticleQualityCheckDefinitionMap is not right. 而且我认为您在ArticleQualityCheckDefinitionMap使用.HasPrincipalKey()的方式不正确。

Principal Key 主键

If you want the foreign key to reference a property other than the primary key, you can use the Fluent API to configure the principal key property for the relationship. 如果希望外键引用主键以外的属性,则可以使用Fluent API为关系配置主键属性。 The property that you configure as the principal key will automatically be setup as an alternate key. 您配置为主键的属性将自动设置为备用键。

Your ArticleQualityCheckDefinitionMap 您的ArticleQualityCheckDefinitionMap

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

By conventions, .HasForeignKey(x => x.ArticleId) will target the primary key of the Article entity, string Id . 按照惯例, .HasForeignKey(x => x.ArticleId)将定位到Article实体的主键, string Id And then you told Entity Framework that you don't want to setup the foreign key to the primary key. 然后,您告诉Entity Framework,您不想将外键设置为主键。 You want to target another property called Id by saying .HasPrincipalKey(x => x.Id) . 您想通过说.HasPrincipalKey(x => x.Id)来定位另一个名为Id的属性。

Huh? ?? Aren't they the same? 他们不一样吗? That's why I think Entity Framework got confused. 这就是为什么我认为实体框架感到困惑。 And since you don't have a configuration for Article , Entity Framework tried its best to generate a primary key for you, called "ArticleId"? 而且,由于您没有 Article的配置,因此Entity Framework会尽力为您生成一个称为“ ArticleId”的主键?

You can fix the problem by just adding the configurations back and removing .HasPrincipalKey() there. 您可以通过仅添加配置并在其中删除.HasPrincipalKey()来解决问题。

StockItemConfiguration 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));
        }
    }
}

You might need to configure for QualityCheckDefinition as well: 您可能还需要配置QualityCheckDefinition

QualityCheckDefinitionConfiguration 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));
        }
    }
}

Then remove .HasPrincipalKey() : 然后删除.HasPrincipalKey()

ArticleQualityCheckDefinitionConfiguration 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));
        }
    }
}

Then you should be fine? 那你应该没事吗

在此处输入图片说明

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

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