为了模拟延迟加载,我希望有一个递归的方法通过Eager Loading包含完整的对象图,这样在加载实体时,它的所有相关数据也会被加载。
来自MSDN文档:
问题:
如何递归地包含所有可导航属性并将其构建到通用存储库方法中,以便在需要时可以获得实体的深层对象图,无论是否添加了新属性?
答案 0 :(得分:3)
好的,这是一个经过编辑的版本,可以更好地满足您的要求:
private static void EnumerateAllIncludesList(DbContext context, IEnumerable entities, List<object> entitiesLoaded = null)
{
if (entitiesLoaded == null)
entitiesLoaded = new List<object>();
foreach (var entity in entities)
EnumerateAllIncludesEntity(context, entity, entitiesLoaded);
}
private static void EnumerateAllIncludesEntity(DbContext context, object entity, List<object> entitiesLoaded)
{
if (entitiesLoaded.Contains(entity))
return;
entitiesLoaded.Add(entity);
Type type = entity.GetType();
var properties = type.GetProperties();
foreach (var propertyInfo in properties)
{
var propertyType = propertyInfo.PropertyType;
bool isCollection = propertyType.GetInterfaces().Any(x => x == typeof(IEnumerable)) &&
!propertyType.Equals(typeof(string));
if (isCollection)
{
var entry = context.Entry(entity);
if(entry.Member(propertyInfo.Name) as DbCollectionEntry == null)
continue;
entry.Collection(propertyInfo.Name).Load();
var propertyValue = propertyInfo.GetValue(entity);
if (propertyValue == null)
continue;
EnumerateAllIncludesList(context, (IEnumerable)propertyValue, entitiesLoaded);
}
else if ((!propertyType.IsValueType && !propertyType.Equals(typeof(string))))
{
var entry = context.Entry(entity);
if (entry.Member(propertyInfo.Name) as DbReferenceEntry == null)
continue;
entry.Reference(propertyInfo.Name).Load();
var propertyValue = propertyInfo.GetValue(entity);
if (propertyValue == null)
continue;
EnumerateAllIncludesEntity(context, propertyValue, entitiesLoaded);
}
else
continue;
}
}
你会像这样使用它:
using (var context = new MyContext())
{
var result = context.People.Where(x => x.Id == 1).ToList();
EnumerateAllIncludesList(context,result);
}
答案 1 :(得分:0)
如果您使用模型优先或数据库优先,您可以编写一些T4模板以使用edmx模型生成所需内容。这并不容易,但可能。