将前2列编码为主键/索引

时间:2012-09-12 20:36:58

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

所以我得到了一个名为ObjectA的类,它有很多ObjectsB,对象有一个Id,用于识别它们,但也是一种语言(枚举,但它实际上保存为和INT,对于这种情况也无关紧要)。 / p>

public class ObjectA
{
       public int Id {get;set;}
       public Language Language {get;set;}
       ... // and a list of objectA properties

       public virtual ICollection<ObjectB> ObjectBs {get;set;}
}

public class ObjectB
{
       public int Id {get;set;}
       public Language Language {get;set;}
       ... // and a list of objectB properties

       public ObjectA TheObjectA {get;set;}
}

现在我学会了如何将它们作为主键映射,我使用流畅的API。我知道你也可以使用[Key]和[Column]属性(我不使用):

modelBuilder.Entity<ObjectA>().HasKey(a => new {a.Id, a.Languague})
modelBuilder.Entity<ObjectB>().HasKey(a => new {a.Id, a.Languague})

现在我尝试了很多东西,但我似乎无法将它们彼此连接起来。任何人都知道如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

如果一对多关系中的主体(ObjectA)具有复合主键,则从属(ObjectB)必须具有由与列数相同的外键组成的外键。好。

我假设相关对象A和对象B必须具有相同的语言。在这种情况下,您可以将ObjectB.Language作为外键的第一部分。 (它同时是ObjectB中主键和外键的一部分。)如果在模型中将FK的第二部分暴露为属性,它将如下所示:

(我相信你必须交换IdLanguage以便以下工作。)

public class ObjectA
{
    public Languague Languague {get;set;}
    public int Id {get;set;}
    ... // and a list of objectA properties

    public virtual ICollection<ObjectB> ObjectBs {get;set;}
}

public class ObjectB
{
    public Languague Languague {get;set;}
    public int Id {get;set;}
    ... // and a list of objectB properties

    public int TheObjectAId {get;set;}
    public ObjectA TheObjectA {get;set;}
}

使用Fluent API进行映射:

modelBuilder.Entity<ObjectA>().HasKey(a => new { a.Languague, a.Id })
modelBuilder.Entity<ObjectB>().HasKey(b => new { b.Languague, b.Id })

modelBuilder.Entity<ObjectA>()
    .HasMany(a => a.ObjectBs)
    .WithRequired(b => b.ObjectA)
    .HasForeignKey(b => new { b.Language, b.TheObjectAId });

如果语言不同,请为该语言引入单独的FK属性:

    public Language TheObjectALanguage {get;set;}
    public int TheObjectAId {get;set;}
    public ObjectA TheObjectA {get;set;}

...和地图:

modelBuilder.Entity<ObjectA>()
    .HasMany(a => a.ObjectBs)
    .WithRequired(b => b.ObjectA)
    .HasForeignKey(b => new { b.TheObjectALanguage, b.TheObjectAId });

如果关系是可选的,请使用WithOptional代替WithRequired,并使FK属性可以为空:

public Language? TheObjectALanguage {get;set;}
public int? TheObjectAId {get;set;}

我不希望您的模型中有FK属性,您可以将MapKey与Fluent API一起使用:

modelBuilder.Entity<ObjectA>()
    .HasMany(a => a.ObjectBs)
    .WithRequired(b => b.ObjectA)
    .Map(m => m.MapKey("TheObjectALanguage, TheObjectAId")); // FK columns