问题描述
我有以下的数据结构:
//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;
}
我收到以下错误:
I get the following error:
国外关键部件TenantId'是不是在
类声明的属性SpecialOrder。确认它没有被明确排除
从模型中,它是一个有效的基本属性。
错误使用在流利的API配置:
Error occurs using the Fluent Api Configuration:
config.HasRequired(p => p.OtherClass)
.WithMany(oc => oc.SpecialOrders)
.HasForeignKey(p => new { p.TenantId, p.OtherClassId});
如果没有在 OtherClass
参考 SpecialOrder
我可以自由地创建对象没有问题(包括 SpecialOrder
, SuperSpecialOrder
等)。
Without the OtherClass
reference in SpecialOrder
I can create objects freely without problems (including SpecialOrder
, SuperSpecialOrder
etc).
任何人都有一个线索,这是怎么回事?我在这里失去了:(
Anyone have a clue what's going on? I'm lost here :(
修改
我在其他问题看出,人们去除表TenantId,这是不是一种选择,因为主键是不能跨租户独特的,我们要保持的共享数据架构。
EditI've seen in other questions that people remove the TenantId from tables, this is not an option since primary keys are not unique across tenants and we want to keep the shared data architecture.
我知道解决办法是有在SpecialOrder类第二TenantId ,但是这似乎并不符合逻辑的我。
I know the workaround is having a second TenantId in the SpecialOrder class, but this does not seem logical to me.
推荐答案
您试图做一个TPT,那里有一个单独的表订单/租户?如果是这样,我觉得其他的海报是正确的,有一个在EF的错误。
Are you trying to do a TPT, where there's a separate table for Order/Tenant? If so, I think the other poster is correct, and there's a bug in EF.
如果客户/产品是您根据映射类,这可能会为工作你。
If customers/products are your based mapped classes, this might work for you.
什么发生在我身上时,我创建你的数据库是它试图绘制抽象Order类。
What happened to me when I created your database is it tried to map the abstract Order class.
通过添加:
modelBuilder.Ignore<Order>();
建设者不停由于MapInheritedProperties映射属性,但没有创建表,以便所有的FK的是正确创建。
The builder kept the mapped properties due to the MapInheritedProperties, but didn't create the table so that all the FK's were correctly created.
我假设你想为每个类的像上面的相关职位单独的表,并且不图你的抽象表。
I'm assuming you wanted separate tables for each of your classes like the related post above, and to not map your abstract table.
整个模型:
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>();
}
}
创建的数据库:
Created Database:
希望这有助于。
这篇关于Entity Framework的多租户共享数据结构:单立柱,多个外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!