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;
}

次のエラーが表示されます。

外部キー コンポーネント 'TenantId' は、タイプ 'SpecialOrder' で宣言されたプロパティではありません。モデルから明示的に除外されていないこと、および有効なプリミティブ プロパティであることを確認してください。

Fluent Api 構成を使用するとエラーが発生します。

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

OtherClassの参照がなければ、SpecialOrder問題なく自由にオブジェクトを作成できます ( などを含むSpecialOrder) SuperSpecialOrder

誰が何が起こっているのか手がかりを持っていますか? 私はここで迷っています:(

他の質問で、人々がテーブルからTenantId を削除するのを見たことがありますが、主キーはテナント間で一意ではなく、共有データ アーキテクチャを維持したいため、これはオプションではありません。

回避策として SpecialOrder クラスに 2 番目の TenantId があることは知っていますが、これは論理的ではないように思えます。

4

2 に答える 2

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>();


      }
   }

作成されたデータベース: ここに画像の説明を入力

お役に立てれば。

于 2012-08-22T03:18:00.173 に答える
0

Julie Lermannがef4.1で行ったブログで異常なバグを見たので、ここで推測します。クエリの名前空間が問題を引き起こしました。

このバグが問題であるかどうかをすばやくテストするには、すべてのオブジェクトの名前空間を同じに変更します。名前空間xyz//dbcontextおよびエンティティと同じpublicclassOtherClass {}

クイックテスト。そうでない場合は、時間を無駄にして申し訳ありません。

于 2012-08-22T14:46:54.740 に答える