如何使用非主键的字段在表之间进行映射?

时间:2012-08-20 04:25:13

标签: c# entity-framework-4 ef-code-first

我有两个表定义如下:

CREATE TABLE [SomeTable] (
[PrincipalID] [int] IDENTITY(1,1) NOT NULL,
[AnotherUniqueField] [varchar](50) NOT NULL,
[Data] [varchar](50) NOT NULL,
CONSTRAINT [PK_SomeTable] PRIMARY KEY CLUSTERED ([PrincipalID] ASC))

CREATE TABLE [OtherTable] (
[OtherID] [int] NOT NULL,
[UniqueIfNotNullField] [varchar](20) NULL,
[OtherData] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_OtherTable] PRIMARY KEY CLUSTERED ([OtherID] ASC))

这两个表记录了相同概念对象的信息,我希望能够在我拥有的EF实体中创建它们之间的关系,使用SomeTable.AnotherUniqueFieldOtherTable.UniqueIfNotNullField作为“键“。

SomeTable.AnotherUniqueField有一个独特的索引,但显然不是PK。如上所述,OtherTable.UniqueIfNotNullField在值不为空时是唯一的。 (此约束不会在数据库中强制执行,但会保留表数据的来源以保证在有值时保持唯一性。)

以下是POCO实体:

public class SomeTable
{
    public int PrincipalID { get; set; }
    public int SameField { get; set; }
    public string Data { get; set; }
    public OtherTable Other { get; set; }
}

public class OtherTable
{
    public int OtherID { get; set; }
    public string SameField { get; set; }
    public string OtherData { get; set; }
}

我的EntityTypeConfiguration定义相同:

public class SomeTableMap : EntityTypeConfiguration<SomeTable>
{
    public SomeTableMap()
    {
        ToTable("SomeTable");
        HasKey(t => t.PrincipalID);
        Property(t => t.Data)
            .IsRequired()
            .HasMaxLength(50);
        Property(t => t.SameField)
            .HasMaxLength(50);
        Property(t => t.PrincipalID).HasColumnName("PrincipalID");
        Property(t => t.SameField).HasColumnName("AnotherUniqueField");
        Property(t => t.Data).HasColumnName("Data");
    }
}

public class OtherTableMap : EntityTypeConfiguration<OtherTable>
{
    public OtherTableMap()
    {
        ToTable("OtherTable");
        HasKey(t => t.OtherID);
        Property(t => t.OtherData)
            .IsRequired()
            .HasMaxLength(50);
        Property(t => t.SameField)
            .HasMaxLength(20);
        Property(t => t.OtherID).HasColumnName("OtherID");
        Property(t => t.SameField).HasColumnName("UniqueIfNotNullField");
        Property(t => t.OtherData).HasColumnName("OtherData");
    }
}

这样可以映射吗?我在SomeTableMap的构造函数中尝试了以下内容,但它不起作用。我对自定义映射的理解已经结束了。

HasOptional<OtherTable>(x => x.Other)
    .WithOptionalPrincipal()
    .Map(
        map =>
            {
                map.MapKey("UniqueIfNotNullField");
                map.MapKey("AnotherUniqueField");
            });

这不是一个可映射的连接吗?我有另一种选择,因为OtherTable实际上不是一个可编辑的实体;我可以创建一个包含SomeTable.PrincipalID相关值的视图,但我想看看这是否会先工作。

编辑:我也试过了:

HasOptional(x => x.Other)
    .WithOptionalPrincipal()
    .Map(map => map.MapKey("UniqueIfNotNullField"));

但我收到错误:“Each property name in a type must be unique. Property name 'UniqueIfNotNullField' was already defined.

1 个答案:

答案 0 :(得分:2)

实体框架不支持此关系。核心问题是缺少对EF中唯一约束的支持。因此,主体实体中的键始终必须是主键,如果要构建一对一关系,则依赖实体中的外键也必须是主键。