以下是使用 EF 5.0.0-rc 和 Code First。在我的设计中,我有一个属性实体:
public class Attribute
{
public int AttributeId { get; set; }
public Guid Guid { get; set; }
public string Name { get; set; }
public string Value { get; set; }
/* Used for testing the first fluent statement */
public virtual ICollection<Customer> Customers { get; set; }
}
我还有多个包含 GUID 的实体:
public class Customer
{
public int CustomerId { get; set; }
public Guid Guid { get; set; }
}
public class Location
{
public int LocationId { get; set; }
public Guid Guid { get; set; }
}
我希望属性表对客户表和位置表都是通用的,中间没有列或表。我似乎无法在流畅的 API 中获得正确的映射来创建没有帮助表的 FK:
modelBuilder.Entity<Customer>()
.HasMany(o => o.Attributes)
.WithMany(o => o.Customers)
.Map(m => m.MapLeftKey("Guid"));
... 将生成一个不需要的 CustomerAttributes 表。
modelBuilder.Entity<Organization>()
.HasMany(o => o.Attributes)
.WithOptional()
.HasForeignKey(o => o.Guid);
...不会编译,因为
引用约束的 Dependent Role 中所有属性的类型必须与 Principal Role 中相应的属性类型相同。
应该如何建立关系?还是设计不合适?
编辑:成功!
在 Raphaël Althaus 的指导下,我已准备好接受 EF 的方式,并为每个实体使用单独的跟踪表,但他建议创建一个新类,Cust 和 Loca 实体将继承该类,这让我走上了正确的方向。
首先,我创建了一个“父”类,它也为我提供了重构存储在大多数实体上的一些审计数据的地方:
public class ParentEntity
{
[Key]
public Guid Guid { get; set; }
public DateTime? CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime? ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
[Timestamp]
public byte[] Version { get; set; }
public virtual ICollection<Attribute> Attributes { get; set; }
}
然后我继承了 Cust 和 Loca 实体的父类:
public class Customer : ParentEntity
{
public int CustomerId { get; set; }
public Guid Guid { get; set; }
}
public class Location : ParentEntity
{
public int LocationId { get; set; }
public Guid Guid { get; set; }
}
我还修改了 Attribute 类以支持新的 FK 字段 EntityGuid:
public class Attribute
{
public int AttributeId { get; set; }
public Guid EntityGuid { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
这给了我几乎所有我需要的东西,除了......它试图将每个实体存储在新的 ParentEntity 表中。要解决我使用的问题:
modelBuilder.Entity<Customer>().ToTable("Customers");
modelBuilder.Entity<Location>().ToTable("Locations");
最后是把这一切结合在一起的部分:
modelBuilder.Entity<ParentEntity>()
.HasMany(e => e.Attributes)
.WithRequired()
.HasForeignKey(e => e.EntityGuid);
我能说的唯一缺点是 ParentEntity 作为主键,它是一个 Guid。但是我保留了我的其他键,并计划将它们用作集群索引。