아쉽게도 ObjectMaterialized 이벤트에서 호출 된 HandleObjectMaterialized 메서드의 자체 추적 엔터티에 IsLoaded 속성을 채우려는 원래 계획이 이벤트 후 많은 수의 컬렉션에만 채워지기 때문에 원하는대로 작동하지 않았습니다. this 게시물). 그리고 추적하고있는 각 엔티티에 대한 컨텍스트에서 관계를 반복하고, IsLoaded 속성을 테스트하고 자체 추적 엔터티에 해당 IsLoaded 속성을 설정하려고했습니다.
그래서 대신에 나는이 같은 대한 반사를 사용하는 첫 번째()와 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;
}
이 솔루션은 약간 I가 한 점에서 dissapointing한다 올바른 탐색 (예 : Person.Address 대신 Person.Addresses)을 얻으려면 봉인 된 속성 "NavigationProperty"에 액세스 한 다음 NavigationProperty.Identity에 액세스하십시오. 다행히 뭔가 더 우아한 뭔가가 미래에 나타날 것입니다.
이
<#
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;
}
<#
}
#>
이를 위해 내장 어디에도 없습니다 만,이는 내가 같은 주소에 대한 AddressesIsLoaded 속성을 만들어 내게 예를 들어, 사람에의 IsLoaded 표시 속성을 만들 내 유형 T4 템플릿을 업데이트 작동하기 위해서는
주 당신은 직접 그것을 쓸 수 있습니다. –