简体   繁体   English

列不是主键时与EF Code First的一对零或一对关系

[英]One-to-Zero-or-One relationship with E.F. Code First when column is not primary key

I'm developing an Entity Framework 6.1.3 Code First library, C# and .NET Framework 4.5.1. 我正在开发Entity Framework 6.1.3代码优先库,C#和.NET Framework 4.5.1。

I have a problem with a One-to-Zero-or-One relationship (or maybe is another kind of relationship). 我对一对零或一个关系(或者可能是另一种关系)有疑问。

I have two tables, Codes and HelperCodes , a code could have zero or one helper code. 我有两个表CodesHelperCodes ,一个代码可以有零个或一个helper代码。 This is the sql script to create these two tables and their relationships: 这是用于创建这两个表及其关系的sql脚本:

CREATE TABLE [dbo].[Code]
(
    [Id] NVARCHAR(20) NOT NULL, 
    [Level] TINYINT NOT NULL, 
    [CommissioningFlag] TINYINT NOT NULL, 
    [SentToRanger] BIT NOT NULL DEFAULT 0, 
    [LastChange] NVARCHAR(50) NOT NULL, 
    [UserName] NVARCHAR(50) NOT NULL, 
    [Source] NVARCHAR(50) NOT NULL, 
    [Reason] NVARCHAR(200) NULL, 
    [HelperCodeId] NVARCHAR(20) NULL,
    CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    ),
    CONSTRAINT [FK_Code_LevelConfiguration]
       FOREIGN KEY ([Level])
        REFERENCES [dbo].[LevelConfiguration] ([Level]),
    CONSTRAINT [FK_Code_HelperCode]
       FOREIGN KEY ([HelperCodeId])
        REFERENCES [dbo].[HelperCode] ([HelperCodeId])
)

CREATE TABLE [dbo].[HelperCode]
(
    [HelperCodeId] NVARCHAR(20) NOT NULL, 
    [Level] TINYINT NOT NULL, 
    [CommissioningFlag] TINYINT NOT NULL, 
    [LastChange] NVARCHAR(50) NOT NULL,
    CONSTRAINT [PK_HelperCode] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    ),
    CONSTRAINT [FK_HelperCode_LevelConfiguration]
       FOREIGN KEY ([Level])
        REFERENCES [dbo].[LevelConfiguration] ([Level])
)

But, when I try to do the same with Entity Framework it doesn't do the same. 但是,当我尝试使用Entity Framework做同样的事情时,它却做不到。 My problem is in Codes and HelperCodes foreing key. 我的问题是在Codes和HelperCodes前键中。

This is my Entity Framework Code First code: 这是我的实体框架代码优先代码:

public class Code
    {
        public string Id { get; set; }
        public byte Level { get; set; }

        // omitted for brevity

        public string HelperCodeId { get; set; }

        public virtual HelperCode HelperCode { get; set; }
    }

class CodeConfiguration : EntityTypeConfiguration<Code>
{
    public CodeConfiguration()
    {
        HasKey(c => c.Id);

        Property(c => c.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        Property(c => c.Id)
            .HasMaxLength(20);

        // omitted for brevity

        Property(c => c.HelperCodeId)
            .HasMaxLength(20)
            .IsOptional();

        HasOptional(c => c.HelperCode)
            .WithRequired(hc => hc.Code);
    }
}

public class HelperCode
{
    public string HelperCodeId { get; set; }
    public byte Level { get; set; }
    public byte CommissioningFlag { get; set; }
    public string LastChange { get; set; }

    public virtual Code Code { get; set; }
}

class HelperCodeConfiguration : EntityTypeConfiguration<HelperCode>
{
    public HelperCodeConfiguration()
    {
        HasKey(h => h.HelperCodeId);

        Property(h => h.HelperCodeId)
            .HasMaxLength(20);

        Property(h => h.Level)
            .IsRequired();

        Property(h => h.CommissioningFlag)
            .IsRequired();

        Property(h => h.LastChange)
            .IsOptional()
            .HasMaxLength(50);
    }
}

This Entity Code First code generates a foreign key in HelperCodes table using HelperCodes.HelperCodeId referencing Codes.Id . 这个实体的Code First代码生成的外键HelperCodes使用表HelperCodes.HelperCodeId引用Codes.Id

Entity Framework only allows this kind of relationship if both tables have the same primary key. 如果两个表具有相同的主键,则实体框架仅允许这种关系。

Any idea about how to resolve this EF bug? 关于如何解决此EF错误的任何想法吗?

First: Remove the HelperCodeId from the Code class: 首先:从Code类中删除HelperCodeId

public class Code
{
    public string Id { get; set; }
    public byte Level { get; set; }

    // omitted for brevity

    public virtual HelperCode HelperCode { get; set; }
}

In the Code configuration: Code配置中:

.HasOptional(i => i.HelperCode)
.WithRequired(i => i.Code);

Generated migration: 产生的迁移:

CreateTable(
    "dbo.Codes",
    c => new
        {
            Id = c.String(nullable: false, maxLength: 128),
            Level = c.Byte(nullable: false),
        })
    .PrimaryKey(t => t.Id);

CreateTable(
    "dbo.HelperCodes",
    c => new
        {
            HelperCodeId = c.String(nullable: false, maxLength: 128),
            Level = c.Byte(nullable: false),
            CommissioningFlag = c.Byte(nullable: false),
            LastChange = c.String(),
        })
    .PrimaryKey(t => t.HelperCodeId)
    .ForeignKey("dbo.Codes", t => t.HelperCodeId)
    .Index(t => t.HelperCodeId);

Only the HelperCodes table should have the foreign key statement. 只有HelperCodes表应该具有外键语句。

HelperCodeId is a primary key and also a foreign key, so it ensures the 0:1 relationship. HelperCodeId是一个主键,也是一个外键,因此可以确保0:1的关系。

The relationship is wrong;Change your code to blow code 关系是错误的;将您的代码更改为无效代码

 public class HelperCode
{

    public byte Level { get; set; }
    public byte CommissioningFlag { get; set; }
    public string LastChange { get; set; }
    public string CodeId { get; set; }
    public virtual Code Code { get; set; }
}

  public class Code
{
    public string Id { get; set; }
    public byte Level { get; set; }
    public virtual HelperCode HelperCode { get; set; }
}

I also configure the relationship from the other side. 我还从另一侧配置关系。

public  class CodeConfiguration : EntityTypeConfiguration<Code>
{
    public CodeConfiguration()
    {
        HasKey(h => h.Id);

        HasOptional(x => x.HelperCode).WithRequired(x => x.Code);
    }
}

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

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