gpt4 book ai didi

entity-framework - IsLoaded用于自跟踪实体

转载 作者:行者123 更新时间:2023-12-03 23:39:13 24 4
gpt4 key购买 nike

我将自跟踪实体与EF 4.0一起使用,我发现导航对象没有IsLoaded属性,该对象与标准EF对象一样具有多对多关系。因此,如果您要查询Person而不包含地址,那么person.Addresses会出现一个空列表,但是无法判断地址是否已加载或该人没有任何地址。

有没有办法判断导航属性是否已加载到自跟踪实体上?

如果没有,那么有一种方法可以从ObjectContext访问当前的ObjectQuery,这样我就可以查看用户尝试扩展哪些属性并创建自定义IsLoaded属性?

最佳答案

不幸的是,我最初的计划在HandleObjectMaterialized方法(从ObjectMaterialized事件中调用)中填充自跟踪实体上的IsLoaded属性并没有按期望的那样工作,因为许多集合仅在事件之后被填充(请参见this帖子) )。我想遍历上下文中每个被跟踪实体的关系,测试IsLoaded属性并在我的自跟踪实体上设置相应的IsLoaded属性。

因此,我改为为First()和ToList()创建扩展方法,称为FirstWithLoaded()和ToListWithLoaded(),以便为此使用反射:

public static T FirstOrDefaultWithLoaded<T>(this IQueryable<T> source) where T : new()
{
T result = default(T);
if (source != null)
{
//Call the base FirstOrDefault
result = source.FirstOrDefault();

var querySource = source as ObjectQuery<T>;
if (querySource != null)
{
PopulateIsLoaded(result, querySource.Context);
}
}
return result;
}

private static void PopulateIsLoaded(object inputEntity, ObjectContext dataContext)
{
var entry = dataContext.ObjectStateManager.GetObjectStateEntry(inputEntity);

//var relationShipManagerProperty = entryType.GetProperty("RelationshipManager");//.GetValue(entityType, null);
var relationShipManager = GetPropertyValue(entry, "RelationshipManager");// relationShipManagerProperty.GetValue(entry, null);

if (relationShipManager != null)
{
//get the relationships (this is a sealed property)
var relationships = GetPropertyValue(relationShipManager, "Relationships") as IEnumerable<RelatedEnd>;

if (relationships != null)
{
foreach (RelatedEnd relationship in relationships)
{
//check to see whether the relationship is loaded
var isLoaded = GetRelatedEndPropertyValue(relationship, "IsLoaded");

if (isLoaded != null && (bool)isLoaded)
{
//if the relationship is loaded then set the
//<NavigationPropertyName>IsLoaded on entry to true
var navigationProperty = GetRelatedEndPropertyValue(relationship, "NavigationProperty");
var identity = GetPropertyValue(navigationProperty, "Identity");

//get the IsLoaded property on entry
var isLoadedProperty = entry.Entity.GetType().GetProperty(identity + "IsLoaded");
if (isLoadedProperty != null)
{
isLoadedProperty.SetValue(entry.Entity, true, null);
}
}
}
}
}
}

private static object GetPropertyValue(object inputObject, string propertyName)
{
object result = null;

if (inputObject != null)
{
var property = inputObject.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

if (property != null)
{
result = property.GetValue(inputObject, null);
}
}

return result;
}

private static object GetRelatedEndPropertyValue(RelatedEnd inputObject, string propertyName)
{
object result = null;

if (inputObject != null)
{
PropertyInfo property = null;

property = inputObject.GetType().GetProperty(propertyName, BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

if (property != null)
{
result = property.GetValue(inputObject, null);
}
}

return result;
}


该解决方案有点让人失望,因为我必须访问密封属性“ NavigationProperty”,然后访问NavigationProperty.Identity才能获得正确的导航(例如,Person.Addresses而不是Person.Address)。希望将来会有更优雅的表现。

请注意,为了使其正常工作,我更新了Types T4模板以为我创建IsLoaded属性,例如,在Person上,我为Addresses创建了AddressesIsLoaded属性为:

<#
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
//The IsLoaded property for use on the client side when including collections
[DataMember]
<#=Accessibility.ForReadOnlyProperty(navProperty)#> bool <#=code.Escape(navProperty)#>IsLoaded
{
get; set;
}
<#
}
#>

关于entity-framework - IsLoaded用于自跟踪实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1938298/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com