我有以下数据结构:
//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”不是声明的属性
输入“特殊订单”。验证是否未明确排除
来自模型并且它是有效的原始属性。
使用 Fluent Api 配置时出现错误:
config.HasRequired(p => p.OtherClass)
.WithMany(oc => oc.SpecialOrders)
.HasForeignKey(p => new { p.TenantId, p.OtherClassId});
如果没有OtherClass
参考文献SpecialOrder
我可以毫无问题地自由创建对象(包括SpecialOrder
, SuperSpecialOrder
etc).
有人知道发生了什么事吗?我在这里迷路了:(
Edit我在其他问题中看到人们从表中删除 TenantId,这不是一个选项,因为主键在租户之间不是唯一的,并且我们希望保留共享数据架构。
我知道解决方法是在 SpecialOrder 类中添加第二个 TenantId,但这对我来说似乎不合逻辑。
您是否正在尝试执行 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>();
}
}
Created Database:
希望这可以帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)