给定一个 EntityCollection<T>,如何确定它的所有者是否分离?
Given an EntityCollection<T>, how to find out whether it's owner is detached or not?
我需要查明给定 EntityCollection<T>
的所有者是否与上下文分离。原因是为了避免对集合的后续 Load() 调用失败。但是,集合的 _owner
和 _wrappedOwner
字段不可访问,并且似乎没有可用的元数据提供此信息。
有没有办法找到所有者(或者至少是 EntityState)?
上下文: 由于政策不允许我们使用延迟加载,因此我想在需要时创建一些简单的显式延迟加载,最好使用通用方法。这就是我目前的做法,要求所有者作为参数:
public static EntityCollection<T> ReloadIfNeeded<T>(this EntityCollection<T> collection, EntityObject owner) where T : EntityObject {
if (owner.EntityState != EntityState.Detached && !collection.IsLoaded) {
collection.Load();
}
return collection;
}
调用示例:
var orders = customer.Orders.ReloadIfNeeded(customer); //I would like to get rid of the customer parameter here...
我正在使用 .NET 4.0 版。
编辑:我的解决方案,实现 Ognyan Dimitrov 的答案:
public static EntityCollection<T> ReloadIfNeeded<T>(this EntityCollection<T> collection) where T : EntityObject {
try {
if (!collection.IsLoaded) {
collection.Load();
}
} catch (InvalidOperationException) {
//just leave unloaded
}
return collection;
}
这不考虑最初寻求的实体状态,但以 try/catch 子句为代价摆脱了不需要的参数。
将 EntityCollection 与 Reflector 相结合并查看代码,我发现此 class 有一个 public 方法
public override void Load(MergeOption mergeOption)
{
base.CheckOwnerNull();
this.Load(null, mergeOption);
}
然后调用另一个内部 Load 方法:
internal void Load(List<IEntityWrapper> collection, MergeOption mergeOption)
{
bool flag;
ObjectQuery<TEntity> query = base.ValidateLoad<TEntity>(mergeOption, "EntityCollection", out flag);
base._suppressEvents = true;
try
{
if (collection == null)
{
base.Merge<TEntity>(flag ? RelatedEnd.GetResults<TEntity>(query) : Enumerable.Empty<TEntity>(), mergeOption, true);
}
else
{
base.Merge<TEntity>(collection, mergeOption, true);
}
}
finally
{
base._suppressEvents = false;
}
this.OnAssociationChanged(CollectionChangeAction.Refresh, null);
}
看起来它会在内部检查所有者是否在那里,如果您捕获到异常,这将使您免于 'failing subsequent Load()'。如果您在指定的任何时刻使用 MergeOption 调用 Load(MergeOption)。
在您的情况下,'Detached' 是否意味着实体刚从 POST 请求的前端传来?如果您之前有权访问父实体,则可以使用以下方式检查其状态:
_context.Entry(entity).State
我不知道分离父实体是否会反映在将子实体的 'state' 设置为相同状态。
我需要查明给定 EntityCollection<T>
的所有者是否与上下文分离。原因是为了避免对集合的后续 Load() 调用失败。但是,集合的 _owner
和 _wrappedOwner
字段不可访问,并且似乎没有可用的元数据提供此信息。
有没有办法找到所有者(或者至少是 EntityState)?
上下文: 由于政策不允许我们使用延迟加载,因此我想在需要时创建一些简单的显式延迟加载,最好使用通用方法。这就是我目前的做法,要求所有者作为参数:
public static EntityCollection<T> ReloadIfNeeded<T>(this EntityCollection<T> collection, EntityObject owner) where T : EntityObject {
if (owner.EntityState != EntityState.Detached && !collection.IsLoaded) {
collection.Load();
}
return collection;
}
调用示例:
var orders = customer.Orders.ReloadIfNeeded(customer); //I would like to get rid of the customer parameter here...
我正在使用 .NET 4.0 版。
编辑:我的解决方案,实现 Ognyan Dimitrov 的答案:
public static EntityCollection<T> ReloadIfNeeded<T>(this EntityCollection<T> collection) where T : EntityObject {
try {
if (!collection.IsLoaded) {
collection.Load();
}
} catch (InvalidOperationException) {
//just leave unloaded
}
return collection;
}
这不考虑最初寻求的实体状态,但以 try/catch 子句为代价摆脱了不需要的参数。
将 EntityCollection 与 Reflector 相结合并查看代码,我发现此 class 有一个 public 方法
public override void Load(MergeOption mergeOption)
{
base.CheckOwnerNull();
this.Load(null, mergeOption);
}
然后调用另一个内部 Load 方法:
internal void Load(List<IEntityWrapper> collection, MergeOption mergeOption)
{
bool flag;
ObjectQuery<TEntity> query = base.ValidateLoad<TEntity>(mergeOption, "EntityCollection", out flag);
base._suppressEvents = true;
try
{
if (collection == null)
{
base.Merge<TEntity>(flag ? RelatedEnd.GetResults<TEntity>(query) : Enumerable.Empty<TEntity>(), mergeOption, true);
}
else
{
base.Merge<TEntity>(collection, mergeOption, true);
}
}
finally
{
base._suppressEvents = false;
}
this.OnAssociationChanged(CollectionChangeAction.Refresh, null);
}
看起来它会在内部检查所有者是否在那里,如果您捕获到异常,这将使您免于 'failing subsequent Load()'。如果您在指定的任何时刻使用 MergeOption 调用 Load(MergeOption)。
在您的情况下,'Detached' 是否意味着实体刚从 POST 请求的前端传来?如果您之前有权访问父实体,则可以使用以下方式检查其状态:
_context.Entry(entity).State
我不知道分离父实体是否会反映在将子实体的 'state' 设置为相同状态。