Это не вопрос с практическими рекомендациями, а скорее почему и как это работает.Дело в том, что когда в его assembly
два namespaces
есть два contexts
, реализующих разные части дерева TPT
, но совместно использующих базовые таблицы, добавление новой сущности завершается неудачно при вызове SaveChanges()
в контексте с UpdateException: Error retrieving values from ObjectStateEntry. See inner exception for details.
выбрасывается.Внутреннее исключение гласит, что
(41,10): ошибка 3032: проблема в отображении фрагментов, начинающихся со строк 41, 47: EntityTypes app.a.ChildB, app.a.ChildA сопоставляются сте же строки в таблице xBase.Условия сопоставления могут использоваться для различения строк, в которые отображаются эти типы.
Первый вопрос: что это за номера строк, на что они ссылаются?
Теперь, учитывая код:
namespace app
{
public abstract class xBase
{
//...
}
}
namespace app.a
{
public class ChildA : xBase
{
//...
}
public class AContext : DbContext
{
public DbSet<xBase> Base { get; set; }
public DbSet<ChildA> Children { get; set; }
public AContext()
: base("name=AppAContext")
{
this.Configuration.LazyLoadingEnabled = false;
}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("PlayGround");
modelBuilder.Configurations.Add(new xBaseConfiguration());
modelBuilder.Configurations.Add(new ChildAConfiguration());
}
public class xBaseConfiguration: EntityTypeConfiguration<xBase>
{
public xBaseConfiguration()
{
//...
this.Map(m => {
m.ToTable("xBase");
});
}
}
public class ChildAConfiguration : EntityTypeConfiguration<ChildA>
{
public ChildAConfiguration ()
{
//...
this.Map(m => {
m.ToTable("AChildren");
});
}
}
}
}
namespace app.b
{
public class ChildB : xBase
{
//...
}
public class BContext : DbContext
{
public DbSet<xBase> Base { get; set; }
public DbSet<ChildB> Children { get; set; }
public BContext()
: base("name=AppBContext")
{
this.Configuration.LazyLoadingEnabled = false;
}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("PlayGround");
modelBuilder.Configurations.Add(new xBaseConfiguration());
modelBuilder.Configurations.Add(new ChildBConfiguration());
}
public class xBaseConfiguration: EntityTypeConfiguration<xBase>
{
public xBaseConfiguration()
{
//...
this.Map(m => {
m.ToTable("xBase");
});
}
}
public class ChildBConfiguration : EntityTypeConfiguration<ChildB>
{
public ChildBConfiguration()
{
//...
this.Map(m => {
m.ToTable("BChildren");
});
}
}
}
}
Примечание: оба контекста используют разные имена, но указывают на один и тот же экземпляр БД.Затем, когда кто-то пытается добавить, например, новое ChildA
, вышеупомянутое исключение выдается, как в этом примере:
using (var db = new AContext())
{
var child = new AChild();
//...
db.Children.Add(child);
db.SaveChanges(); //<--At this point the exception is thrown
}
В случае, если один исключает из сборки любую из частей дерева, кодкоторый работает со второй частью работает по желанию.Теперь, это может быть связано с этим поведением или нет, но по какой-то причине, как мы можем видеть в сообщении об исключении, платформа думает, что обе части иерархии находятся в одном и том же пространстве имен, что не так, изначально они былиИтак, я начал с их разделения, но ничего не изменилось, затем я разделил строки подключения, используемые в двух контекстах, но все же получил такое же поведение.Стоит отметить, что исключение выдается, даже если создается только один из контекстов, и как только первый дочерний элемент вставляется и вызывается SaveChanges()
.Так как и почему один контекст знает о существовании других сущностей в другом пространстве имен?