【问题标题】:Two primarykeys on same table and foreignkey同一张表上的两个主键和外键
【发布时间】:2016-08-02 09:54:51
【问题描述】:

我有两张表,其中一张与另一张相关。 第一张表

 public class Text
  {
    [Key]
    [Column(Order = 1)]
    [Required]
    [MinLength(7)]
    [MaxLength(7)]
    public string Fieldname { get; set; }

    [Key]
    [Column(Order = 2)]
    [Required]
    public virtual Language Language { get; set; }

    [MaxLength(50)]
    [MinLength(1)]
    [Required]
    public string Description { get; set; }
  }

还有第二张桌子:

public class Language
  {
    [Key]
    [Required]
    [MaxLength(2), MinLength(2)]
    public string Code { get; set; }
    [Required]
    public string Country { get; set; }
  }

种子数据如下:

context.Language.AddOrUpdate(
        new Language() {Code = "DE", Country = "German"},
        new Language() {Code = "EN", Country = "English"});

context.Text.AddOrUpdate(
        new Text { Fieldname = "TEXT001", Description = "Server", Language = context.Language.First(e => e.Code == "EN") },
        new Text { Fieldname = "TEXT001", Description = "Server", Language = context.Language.First(e => e.Code == "DE") }
      );

我更新数据库并收到以下错误消息:

System.Data.Entity.Core.UpdateException:更新条目时出错。有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient.SqlException:违反主键约束“PK_dbo.Texts”。无法在对象“dbo.Texts”中插入重复键。重复键值为 (TEXT001)。

怎么了?

【问题讨论】:

  • 是的,但与字段 FieldnameLanguage 结合使用。请看种子数据,然后你应该是我的意思。
  • @zero_coding - 不确定,但我认为您应该指定 Language key 是外键 - [Key, ForeignKey("Language"), Column(Order=2)]
  • 将复杂属性Language 设置为密钥有效吗?

标签: c# entity-framework


【解决方案1】:

@IvanStoev 的回答是正确的。但我想展示另一种选择。我建议使用 Fluent API 映射您的类。相信我,这样一来,您的模型将保持更清晰,并且映射更易于理解。

文本模型及其映射:

public class Text
{
    public string FieldName { get; set; }  
    public string LanguageCode { getl set; } // Add this foriegn key property
    public string Description { get; set; }

    // Navigation properties
    public virtual Language Language { get; set; }
}

internal class TextMap
    : EntityTypeConfiguration<Text>
{
    public TextMap()
    {
        // Primary key
        this.HasKey(m => new { m.FieldName, m.LanguageCode });

        this.Property(m => m.FieldName)
                .HasMaxLength(7)
                .IsFixedLength();

        this.Property(m => m.LanguageCode)
                .HasMaxLength(2)
                .IsFixedLength();

        // Properties
        this.Property(m => m.Description)
            .IsRequired()
            .HasMaxLength(50);                      

        // Relationship mappings
        this.HasRequired(m => m.Language)
            .WithMany()
            .HasForeignKey(m => m.LanguageCode)
            .WillCascadeOnDelete(false);
    }
}

语言模型及其映射:

public class Language
{
    public string Code { get; set; }
    public string Country { get; set; }
}

internal class LanguageMap
    : EntityTypeConfiguration<Language>
{
    public LanguageMap()
    {
        // Primary key
        this.HasKey(m => m.Code);

        this.Property(m => m.Code)
                .HasMaxLength(2)
                .IsFixedLength();

        // Proeprties
        this.Property(m => m.Country)
            .IsRequired();
    }
}

那么你应该重写 DbContext 的 OnModelCreating 方法并将你的映射添加为:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new TextMap());
    modelBuilder.Configurations.Add(new LanguageMap());
}

【讨论】:

  • 所以在导航属性中,我不必再设置[Key]了?
  • 您在 Navigation 属性中有主键,但如果您使用 Fluent API @zero_coding,则不使用任何属性
  • 啊哈好吧。我会试一试,然后告诉你。
  • 我按照你上面的描述做了,例如删除所有属性等。当我做Update-Database时,我得到了以下错误The object 'DF__Texts__Fieldname__21B6055D' is dependent on column 'Fieldname'
  • 这可以帮助我stackoverflow.com/questions/19460912/…。谢谢
【解决方案2】:

我认为您不能使用导航属性定义部分 PK,因此 EF 只是忽略了 Language 属性上的 ColumnKey 属性,最终 PK 只是 Fieldname

您需要像这样明确地包含 FK 字段:

public class Text
{
    [Key]
    [Column(Order = 1)]
    [Required]
    [MinLength(7)]
    [MaxLength(7)]
    public string Fieldname { get; set; }

    [Key]
    [Column(Order = 2)]
    [Required]
    [MaxLength(2), MinLength(2)]
    public string LanguageCode { get; set; }

    [ForeignKey("LanguageCode")]
    public virtual Language Language { get; set; }

    [MaxLength(50)]
    [MinLength(1)]
    [Required]
    public string Description { get; set; }
}

【讨论】:

    猜你喜欢
    • 2013-01-06
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 2015-12-30
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多