簡體   English   中英

實體框架6 - 導航屬性的主鍵

[英]Entity Framework 6 - primary key on navigation property

使用Code First方法和Entity Framework 6.1.3 ,我正在嘗試根據這篇文章創建和配置我自己的多對多表。 非常同意他的看法:我不想遵守這些慣例,因為這限制了我的設計。

看看Code First中的多對多有效載荷類:

public class FooBar
{
    [Key, Column(Order = 1)]
    public virtual Foo Foo { get; set; }

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

    //some more 'payload' properties
}

我想保持這種方式而不添加標量屬性。 所以,我希望在我的模型這些屬性:

public int FooId { get; set; }
public int BarId { get; set; }

我的問題是明確是否有可能在實體框架6有一個導航屬性這樣的(復合)鍵? 此問題的大多數答案都是基於早期版本的Entity Framework,因此無法實現。 所以問題是,現在可能嗎?

這個答案中,它提到:

您需要以特定方式設置類,以便EF識別您嘗試實現的目標。

但是,如果它在技術上可行,我仍然不清楚。 如果是,有人可以在代碼中提供如何實現這一目標的示例嗎?

不能這樣做

不僅使用EF 6.X,而且EF Core也不可能。 這是設計的。 如果您不在聯結表上定義這些標量屬性,EF不知道如何映射關系。 我不得不說,這是設計的。 不幸的是,你在這里沒有任何其他選擇。 您必須在聯結表上包含這些標量屬性。

我希望這對某些人有用。

經過幾個小時的搜索引擎搜索,我終於在這里做到了。 可悲的是,你和我所面臨的同樣問題都沒有答案。 我只是不想撤回我的設計選擇並創建許多標量類型,就像你在帖子中所說的那樣。

我想出了實現基本OOP的解決方案:

// let's assume we would like to have each ObjectModel with
// unique Name and Class properties
// this two data will identify the whole row. (i.e ShadowHawk:Bow)

class ObjectModel {

   public string Name { get; set; }
   public ItemClass ItemClass { get; set; }
   ...
   public MagicAttr[] Attributes { get; set; }
   ...
}

class ObjectEntity : ObjectModel {

   public int Class_id
   ...
   other foreign keys as primary keys
}

使用這種方法,我的ObjectModel仍然是干凈的,獨立於EntityFramework地獄。 我使用Fluent API進行配置,(也可以使用Data anno。原來的ObjectModel仍然很干凈)

在您的上下文中使用ObjectEntity,即DbSet<ObjectEntity>

謹防!

您可能會遇到需要向下轉換方法(從父級轉換為子級)的問題。 這就是我在父類上實現向下轉換的方法(使用AutoMapper)

using AutoMapper;
...
    public ObjectEntity Downcast() {
        var config = new MapperConfiguration(cfg => cfg.CreateMap<ObjectModel, ObjectEntity>());
        var mapper = config.CreateMapper();
        return mapper.Map<ObjectEntity>(this);
    }

想通知你以及:

直接來自MSDN:

https://msdn.microsoft.com/en-us/library/jj591620(v=vs.113).aspx#Anchor_7

重命名未在模型中定義的外鍵如果選擇

如果您選擇不在CLR類型上定義外鍵,但想要指定它在數據庫中應具有的名稱,請執行以下操作:

modelBuilder.Entity<Course>() 
    .HasRequired(c => c.Department) 
    .WithMany(t => t.Courses) 
    .Map(m => m.MapKey("ChangedDepartmentID"));

在努力解決同樣的問題並在網上進行大量研究后,我最終也在這里,最后我放棄了這個想法。 然而,在我的項目的另一部分工作后,我發現這可能實際上是可能的(至少它現在按預期工作)。 但是,在這個例子中使用EF Core。

以刪除關鍵注釋的OP類為例

public class FooBar
{
    public virtual Foo Foo { get; set; }

    public virtual Bar Bar { get; set; }

    //some more 'payload' properties
}

假設Foo和Bar實體類具有如下導航屬性

public class Foo
{
    ...

    public virtual ICollection<FooBar> FooBars { get; set; }
}

public class Bar
{
    ...

    public virtual ICollection<FooBar> FooBars { get; set; }
}

我為FooBar創建了這個配置類

public class FooBarConfiguration : IEntityTypeConfiguration<FooBar>
{
    public void Configure(EntityTypeBuilder<FooBar> builder)
    {
        var fkFoo = "FooId";
        var fkBar = "BarId";

        builder.HasKey(fkFoo, fkBar);

        builder
            .HasOne(fb => fb.Foo)
            .WithMany(f => f.FooBars)
            .HasForeignKey(fkFoo);

        builder
            .HasOne(fb => fb.Bar)
            .WithMany(b => b.FooBars)
            .HasForeignKey(fkBar);
    }
}

並在DbContext類OnModelCreating覆蓋中應用了配置

protected override void OnModelCreating(ModelBuilder builder)
{
    ....

    builder.ApplyConfiguration(new FooBarConfiguration());
}

如上所述,這似乎表現得如預期。 希望它可以幫助其他人搜索同樣的問題。

暫無
暫無

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

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