一段时间以来,我在我的领域设计中一直遵循Object Calisthenics中的“First Class Collections”规则。不过,为了避免创建无用的“集合”表,我使用了实体框架中的表拆分配置。
但是,如果出于某种原因,我有一个Parent
除了其 Id 和子集合之外没有属性的类,我会得到异常:
InvalidOperationException:ReferentialConstraint 中的依赖属性映射到存储生成的列。列:'Id'。
奇怪的是数据库创建正确,我可以从中查询,但无法保存。
如果我只是简单地在 中添加另一个属性Parent
,问题就消失了,这就更奇怪了。
我把它缩小到一个非常简单的测试用例:
程序.cs
class Program
{
static void Main(string[] args)
{
using (var context = new MyContext(new DropCreateDatabaseAlways<MyContext>()))
{
context.Set<Parent>().Find(1);
}
using (var context = new MyContext(new CreateDatabaseIfNotExists<MyContext>()))
{
context.Set<Parent>().Add(
new Parent()
{
ChildrenCollection = new ChildrenCollection()
{
List = new List<Child>() { new Child() }
}
});
context.SaveChanges(); // Exception thrown here
}
}
}
领域
public class Parent
{
public int Id { get; set; }
public virtual ChildrenCollection ChildrenCollection { get; set; }
}
public class ChildrenCollection
{
public int Id { get; set; }
public virtual IList<Child> List { get; set; }
}
public class Child
{
public int Id { get; set; }
}
语境
public class MyContext : DbContext
{
public MyContext(IDatabaseInitializer<MyContext> dbInitializer)
: base(nameOrConnectionString: GetConnectionString())
{
Database.SetInitializer(dbInitializer);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ChildrenCollectionConfiguration());
modelBuilder.Configurations.Add(new ParentConfiguration());
base.OnModelCreating(modelBuilder);
}
private static string GetConnectionString()
{
return @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TestEntityFramework;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;MultipleActiveResultSets=true;";
}
}
配置
public class ParentConfiguration : EntityTypeConfiguration<Parent>
{
public ParentConfiguration()
{
HasRequired(x => x.ChildrenCollection)
.WithRequiredPrincipal();
}
}
public class ChildrenCollectionConfiguration : EntityTypeConfiguration<ChildrenCollection>
{
public ChildrenCollectionConfiguration()
{
#region Configure Table Splitting
var parentTable = typeof(Parent).Name;
ToTable(parentTable);
HasMany(x => x.List)
.WithRequired()
.Map(x =>
{
x.MapKey(string.Concat(parentTable, "_Id"));
});
#endregion
}
}