【发布时间】:2019-07-18 01:26:28
【问题描述】:
在 n 层应用程序中,我一直采用从存储库类返回分离实体的方法。然后我在进行更改之前手动附加。在这个新场景之前一切都很好......
我使用以下代码 sn-p 从实体内部访问上下文:
public abstract class EntityBase
{
protected TheLeegzDbContext GetDbContext()
{
ObjectContext object_context = this.ObjectContext();
if (object_context == null || object_context.TransactionHandler == null)
{
return null;
}
return (TheLeegzDbContext)object_context.TransactionHandler.DbContext;
}
private ObjectContext ObjectContext()
{
var field = this.GetType().GetField("_entityWrapper");
if (field == null)
{
return null;
}
var wrapper = field.GetValue(this);
var property = wrapper.GetType().GetProperty("Context");
var context = (ObjectContext)property.GetValue(wrapper, null);
return context;
}
}
这似乎适用于尚未分离的对象。但是,当我通过 .AsNoTracking().FirstOrDefault() 将其分离并稍后附加时,该行:
var field = this.GetType().GetField("_entityWrapper");
返回空值。
总而言之,如果我不分离对象,上面的行确实会检索上下文,但如果我分离然后重新附加对象则失败(注意:我将它附加到与检索它相同的上下文 - -- 不确定这是否重要?!)。
我这样做是因为当添加一个子实体(不是急切加载的)时,根聚合需要加载子实体以使用“序数”,以防新的子实体被“插入”。所以,我想:
1) 检索根对象并分离并...稍后... 2) 将根对象附加到上下文 3) 对根对象调用“AddChild”,(子对象包含一个属性“Ordinal”) 4) 让根对象使用 GetDbContext().Entry(this).Collection(e => e.Children).Load();加载现有的子对象。 5) 如果新项目的序号需要在现有子项中间“插入”,则让根对象操纵现有子对象以“移动”现有子项的序号。
例如
void AddChild(Child child)
if (this.Children == null)
GetDbContext().Entry(this).Collection(e => e.Children).Load();
// Update ordinals of some children if new child ordinal requires inserting.
问题是根的 .Attach 似乎没有提供字段“_entityWrapper”,因为它刚刚从数据库中检索并仍在被跟踪。
我可以做到这一点,或者如果我想插入一个新的孩子,我是否有必要急切地加载现有的孩子?
【问题讨论】:
-
我明白你在做什么,这是延迟急切加载的一个有趣实现,它不像是延迟加载......你是否考虑过简单地添加一个重载来添加允许你通过-在上下文中?
-
谢谢,克里斯。当然是一个选项,但“序数处理”是数据层本身的一种不变行为,所以有点希望域层不必知道这些事情。当然,域层应该知道它需要将实体根附加到上下文,以便可以跟踪更改,但是一旦完成,该根实体上的“添加子项”的实现应该被封装,而域不知道传递 DBContext。我认为“附加”会使实体回到一种状态,就好像它从一开始就从未分离过一样。显然不是。
标签: entity-framework