2012-08-14 92 views
8

我有以下數據結構:實體框架的多租戶共享數據結構:單立柱,多個外鍵

//property Notification 
abstract class BindableBase { } 
//base class for all tenant-scoped objects 
abstract class TenantModelBase : BindableBase 
{ 
    int TenantId; 
} 

abstract class Order : TenantModelBase 
{ 
    Customer Customer; //works: mapped using TenantId and CustomerId 
    Product Product; //again, works with TenantId and ProductId 
    string ProductId; 
    string CustomerId; 
} 
class Customer: TenantModelBase 
{ 
    string CustomerId; 
} 

class Product : TenantModelBase 
{ 
    string ProductId; 
} 

class SpecialOrder : Order 
{ 
    OtherClass OtherClass; //this fails!, see below 
    string OtherClassId; 
} 
class SuperSpecialOrder : SpecialOrder { } 

class OtherClass : TenantModelBase 
{ 
    string OtherClassId; 
} 

我收到以下錯誤:發生

The foreign key component 'TenantId' is not a declared property on type 'SpecialOrder'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

錯誤使用流利的API配置:

 config.HasRequired(p => p.OtherClass) 
      .WithMany(oc => oc.SpecialOrders) 
      .HasForeignKey(p => new { p.TenantId, p.OtherClassId}); 

沒有OtherClass參考SpecialOrder我可以自由地創建對象(包括SpecialOrder,SuperSpecialOrder等)。

任何人都有線索怎麼回事?我在這裏失去了:(

編輯 我在人們取出從表中TenantId其他疑問看出,這是不是一種選擇,因爲主鍵是不能跨租戶獨一無二的,我們希望保持共享數據架構。

我知道了解決方法是一種在SpecialOrder類第二TenantId,但是這似乎並不符合邏輯的我。

+0

我認爲這是一個像這樣的問題:http:// stackoverflow。com/questions/10961690/inheritance-and-composite-foreign-keys-key-in-base-class-the-part-of-the-key-in-base-class--你能更精確地顯示你的映射嗎?什麼是'config'?我猜'EntityTypeConfiguration '''T' ='SpecialOrder',對吧? Order.Customer的映射如何?你用'T' ='SpecialOrder'還是'T' ='Order'創建這個映射? – Slauma 2012-08-16 21:48:00

+0

當我爲Order和SpecialOrder指定映射時,就會出現問題。然後它忽略SpecialOrder在基類中聲明的任何屬性。這看起來確實是同一個問題。 – Bas 2012-08-20 06:31:23

回答

7

你試圖做一個TPT,對訂單,其中有一個單獨的表/租戶?如果是這樣,我認爲另一張海報是正確的,並且EF中存在一個錯誤。

如果客戶/產品是基於您的映射類,這可能適用於您。

當我創建數據庫時發生了什麼,我試圖映射抽象Order類。

通過添加:

modelBuilder.Ignore<Order>(); 

建設者不停由於MapInheritedProperties映射屬性,但並沒有創建表,使所有的FK的是正確創建。

我假設你想爲你的每個類,如上面的相關帖子分開表,並不映射你的抽象表。

整個模型:

public abstract class BindableBase { } 
    //base class for all tenant-scoped objects 
    public abstract class TenantModelBase : BindableBase 
    { 
     [Key] 
     public virtual int TenantId { get; set; } 
    } 

    public abstract class Order : TenantModelBase 
    { 
     public Customer Customer { get; set; } //works: mapped using TenantId and CustomerId 
     public Product Product { get; set; } //again, works with TenantId and ProductId 
     public string ProductId { get; set; } 
     public string CustomerId { get; set; } 
    } 
    public class Customer : TenantModelBase 
    { 
     [Key] 
     public string CustomerId { get; set; } 
    } 

    public class Product : TenantModelBase 
    { 
     [Key] 
     public string ProductId { get; set; } 
    } 

    public class SpecialOrder : Order 
    { 
     [Key] 
     public int SpecialOrderId { get; set; } 
     public OtherClass OtherClass { get; set; } //this fails!, see below 
     public string OtherClassId { get; set; } 
    } 
    public class SuperSpecialOrder : SpecialOrder { } 

    public class OtherClass : TenantModelBase 
    { 
     public string OtherClassId { get; set; } 
     public ICollection<SpecialOrder> SpecialOrders { get; set; } 
    } 



    public class Model : DbContext 
    { 
     public DbSet<Customer> Customers { get; set; } 
     public DbSet<Product> Products { get; set; } 
     public DbSet<SpecialOrder> SpecialOrders { get; set; } 
     public DbSet<SuperSpecialOrder> SuperSpecialOrders { get; set; } 

     public DbSet<OtherClass> OtherClasses { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
     modelBuilder.Entity<OtherClass>() 
      .HasKey(k => new { k.TenantId, k.OtherClassId }); 

     modelBuilder.Entity<Customer>() 
      .HasKey(k => new { k.TenantId, k.CustomerId }); 

     modelBuilder.Entity<Product>() 
      .HasKey(k => new { k.TenantId, k.ProductId }); 


     modelBuilder.Entity<SpecialOrder>() 
      .Map(m => 
        { 
         m.MapInheritedProperties(); 
         m.ToTable("SpecialOrders"); 
        }); 

     modelBuilder.Entity<SpecialOrder>().HasKey(k => new { k.TenantId, k.SpecialOrderId }); 

     modelBuilder.Entity<SuperSpecialOrder>() 
      .Map(m => 
      { 
      m.MapInheritedProperties(); 
      m.ToTable("SuperSpecialOrders"); 
      }) 
      .HasKey(k => new { k.TenantId, k.SpecialOrderId }); 

     modelBuilder.Entity<SpecialOrder>() 
      .HasRequired(p => p.OtherClass) 
      .WithMany(o => o.SpecialOrders) 
      .HasForeignKey(p => new { p.TenantId, p.OtherClassId }); 

     modelBuilder.Entity<Order>() 
      .HasRequired(o => o.Customer) 
      .WithMany() 
      .HasForeignKey(k => new { k.TenantId, k.CustomerId }); 

     modelBuilder.Entity<Order>() 
      .HasRequired(o => o.Product) 
      .WithMany() 
      .HasForeignKey(k => new { k.TenantId, k.ProductId }); 

     modelBuilder.Ignore<Order>(); 


     } 
    } 

創建的數據庫: enter image description here

希望這有助於。

+0

+1:有趣的分析!我發現不是映射'Order'類可以解決問題中的特定問題,但是我想知道問題不僅僅是繼承層次向上移動一層。想象一下,「SuperSpecialOrder」現在有一個對「OtherClass」的引用。因爲基類SpecialOrder現在被映射,所以我猜'SuperSpecialOrder'中的複合FK映射現在會拋出相同的異常。此外,TPC映射,而不是TPT需要得到這個工作? – Slauma 2012-08-22 09:26:38

+0

這似乎是唯一的解決方案,我們必須放棄TPH映射。謝謝你的偉大答案! – Bas 2012-08-23 09:24:19

0

因爲我在博客中看到一個不尋常的錯誤,所以Julie Lermann用ef4.1做了一個 查詢中的命名空間導致了一個問題。

只是爲了快速測試此錯誤是否是您的問題,請將所有對象的命名空間更改爲相同。 命名空間xyz //與dbcontext和and實體相同 public class OtherClass {}

快速測試。如果沒有,對不起浪費你的時間。

+0

你好soadyp,謝謝你的輸入,但是所有的類已經在同一個命名空間了! – Bas 2012-08-23 09:22:31

相關問題