簡體   English   中英

如何在 C# 的外鍵中使用 Entity Framework 的復合主鍵

[英]How to use a composite primary key with Entity Framework from a foreign key in C#

我在現有數據庫和使用實體框架的主鍵/外鍵方面遇到了一個大問題。

它是一個現有的數據庫,不允許更改數據庫,至少不能更改現有的密鑰,因為它們已被其他程序使用。 為了解釋鍵的作用,我添加了一個局部圖。

parameterCodeType是字符串索引鍵,因此它們與普通 ID 一樣

該數據庫由 4 個表組成:

范圍

這具有以下主鍵列(形成復合鍵):

  • 參數代碼
  • 類型 => 此鍵是參數類型的一部分

參數類型

這具有以下主鍵:

  • ParameterTypeCode => 連接到輸入參數。

參數文檔類型

主鍵:ParameterDocumentId

這具有以下外鍵

  • ParamaterCode => 連接到參數
  • 類型 => 連接到參數
  • ParameterDocument => 這個工作正常,所以我把它放在外面

我創建了配置和模型來連接所有表,但是連接到parameterTypeParameter表不接受配置。 當我將兩個鍵都聲明為主鍵時。

當連接也是主鍵一部分的parametertype類型外鍵時,出現以下錯誤:

System.InvalidOperationException:“無法將屬性或導航‘ParameterType’添加到實體類型‘ParameterModel’,因為實體類型‘ParameterModel’上已存在同名的屬性或導航。”

我從所有其他值中剝離代碼以使其更小。

數據結構

[![// configurations
public class ParameterConfiguration : IEntityTypeConfiguration<ParameterModel>
{
        public void Configure(EntityTypeBuilder<ParameterModel> builder)
        {
            builder.ToTable("Parameter", table => table.ExcludeFromMigrations());

            builder.HasKey(p => new { p.ParameterCode, p.ParameterType });

            builder.Property(p => p.ParameterCode)
                .HasColumnName("ParameterCode")
                .HasColumnType("varchar(25)")
                .IsRequired();

            builder.Property(p => p.Description)
                .HasColumnName("Description")
                .HasColumnType("varchar(255)");
                .IsRequired();

            builder.HasOne(x => x.ParameterType) // error on creating this key
                .WithMany(x => x.Parameters)
                .HasForeignKey(x => x.Type)
                .IsRequired();
        }
}

// configurations ParameterTypeConfiguration
public class ParameterTypeConfiguration : IEntityTypeConfiguration<ParameterTypeModel>
{
        public void Configure(EntityTypeBuilder<ParameterTypeModel> builder)
        {
            builder.ToTable("ParameterType", table => table.ExcludeFromMigrations());

            builder.HasKey(p => p.ParameterTypeCode);

            builder.Property(p => p.ParameterTypeCode)
                .HasColumnName("ParameterTypeCode")
                .HasColumnType("varchar(50)")
                .IsRequired();

        }
}

// configurations
public void Configure(EntityTypeBuilder<ParameterDocumentTypeModel> builder)
{
            builder.ToTable("ParameterDocumentType", table => table.ExcludeFromMigrations());

            builder.HasKey(p => p.ParameterDocumentTypeId);

            builder.Property(p => p.ParameterDocumentTypeId)
                .HasColumnName("ParameterDocumentTypeID")
                .HasColumnType("bigint")
                .UseIdentityColumn()
                .ValueGeneratedOnAdd()
                .IsRequired();

            builder.Property(p => p.ParameterCode)
                .HasColumnName("Parameter_Code")
                .HasColumnType("varchar(50)")
                .IsRequired();

            builder.Property(p => p.Type)
                .HasColumnName("Type")
                .HasColumnType("varchar(25)")
                .IsRequired();

            builder.HasOne(p => p.Parameter)
                .WithMany(p => p.ParameterDocumentTypes)
                .HasForeignKey(p => p.ParameterCode)
                .IsRequired(false);
        }
}

// models
public class ParameterDocumentTypeModel 
{
        public long ParameterDocumentTypeId { get; set; }
        public long? DocumentTypeId { get; set; }
        
        // used for the connection with parameter
        public virtual ParameterModel Parameter { get; set; }

        public string ParameterTypeCode
        {
            get => Parameter?.Type;
        }
}

public class ParameterModel 
{
        public string ParameterCode { get; set; }
        public string Type { get; set; }

        public virtual ParameterTypeModel ParameterType { get; set; }
        // used to connect to parameterType
        public virtual ICollection<ParameterDocumentTypeModel> ParameterDocumentTypes { get; set; }
}

public class ParameterTypeModel 
{
        public string ParameterTypeCode { get; set; }
        public string Description { get; set; }

        // used to connect to parameter
        public ICollection<ParameterModel> Parameters { get; set; }
}

實體類型“ParameterModel”上已存在同名屬性或導航

因為您試圖將 ParameterType 配置為關鍵屬性,無論如何稍后都會失敗,因為只有標量可以是關鍵屬性。

這個

  builder.HasKey(p => new { p.ParameterCode, p.ParameterType });

應該

  builder.HasKey(p => new { p.ParameterCode, p.Type });

更正后:builder.HasKey(p => new { p.ParameterCode, p.ParameterType });

非常感謝大衛·布朗

我還需要為外鍵做同樣的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM