В течение некоторого времени я следовал правилу «Коллекции первого класса» из Object Calisthenics в моем дизайне домена. Чтобы избежать создания бесполезной таблицы «Collection», я использую конфигурацию разбиение таблицы из Entity Framework.
Но если по какой-то причине у меня есть класс Parent
, который не ' Не имея свойств, кроме его Id и дочерней коллекции, я получаю исключение:
InvalidOperationException: Зависимое свойство в ReferentialConstraint сопоставляется со столбцом, сгенерированным хранилищем. Колонка: 'Id'.
Странно то, что база данных создана правильно, и я могу запросить ее, но сохранение невозможно.
Если я просто добавлю еще одно свойство Parent
, проблема исчезает, что еще более странно.
Я сузил его до очень простого теста:
Program.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
}
}