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我可以毫无问题地自由创建对象(包括SpecialOrderSuperSpecialOrder)。

有人知道发生了什么吗?我在这里迷路了:(

编辑 我在其他问题中看到人们从表中删除 TenantId,这不是一个选项,因为主键在租户之间不是唯一的,我们希望保留共享数据架构。

我知道解决方法是在 SpecialOrder 类中有第二个 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 和实体相同 public class OtherClass{}

快速测试。如果不是,很抱歉浪费您的时间。

于 2012-08-22T14:46:54.740 回答