我有包含的Repository类。下面的代码适用于一对一的关系。但是对于收藏集,我需要将DbContext.Entry(model.Result).Reference(include).Load();
更改为DbContext.Entry(model.Result).Collection(include).Load();
public virtual async Task<TEntity> GetByIdAsync(object[] keyValues,
List<Expression<Func<TEntity, object>>> includes,
CancellationToken cancellationToken = default(CancellationToken))
{
var model = DbSet.FindAsync(keyValues, cancellationToken);
if (includes == null) return await model;
foreach (var include in includes)
//if (include.Body.Type.IsAssignableFrom(typeof(ICollection<>)))
DbContext.Entry(model.Result).Reference(include).Load();
return await model;
//return await DbSet.FindAsync(keyValues, cancellationToken);
}
我可以在这里使用什么样的条件来分隔彼此的引用和集合?
谢谢。编辑: 示例对象是
System.Collections.Generic.IList`1 [[WestCore.Domain.Entities.WestLife.MhpProduct]]
通常,集合可以是ICollection或IList。
答案 0 :(得分:4)
您可以使用更通用的Navigation
方法,而不是单独的Reference
/ Collection
方法。不幸的是,它没有lambda表达式的重载,所以你需要手动提取属性名称。由于您的方法设计不支持嵌套属性,您可以从lambda表达式主体获取该信息,强制转换为MemberExpression
:
foreach (var include in includes)
{
var propertyName = ((MemberExpression)include.Body).Member.Name;
DbContext.Entry(model.Result).Navigation(propertyName).Load();
}
答案 1 :(得分:1)
我改变它而不是明确地模仿FindByIdAsync我有一个稍微灵活的方法:
public async Task<T> GetItemAsync<T>(Expression<Func<T, bool>> filter,
List<Expression<Func<T,object>>> includes) where T: class
{
var model = Set<T>();
foreach (var include in includes)
{
model.Include(include);
}
return await model.FirstOrDefaultAsync(filter);
}
然后你打电话给:
var result = GetItemAsync<MyEntity>(x => x.Id == 3,
new List<Expression<Func<MyEntity, object>>>
{
x => s.SomeProperty,
x => s.SomeOtherProperty
});
这与你的非常相似,但是更灵活一点,只会一次点击数据库,而不是懒得加载所有内容,就像我相信你现有的代码一样。这可能是你的意图,但我们没有这种背景。
另外 - 调用model.Result
并使用非asyc Load()
方法意味着您的代码不像它那样异步友好...
答案 2 :(得分:0)
编辑:
我发现我仍然遇到问题。是
public virtual async Task<TEntity> GetByIdAsync(object[] keyValues,
List<Expression<Func<TEntity, object>>> includes,
CancellationToken cancellationToken = default(CancellationToken))
{
Task<TEntity> model = null;
foreach (var include in includes)
{
if (include.Body.Type.GetInterface(nameof(IEnumerable<TEntity>)) != null)
{ //this part generates SQL Below
await DbSet.Include(include).LoadAsync(cancellationToken);
model = DbSet.FindAsync(keyValues, cancellationToken);
}
else //this part is working
{
var propertyName = ((MemberExpression)include.Body).Member.Name;
model = DbSet.FindAsync(keyValues, cancellationToken);
await DbContext.Entry(model.Result).Navigation(propertyName).LoadAsync(cancellationToken);
}
}
if (model == null)
model = DbSet.FindAsync(keyValues, cancellationToken);
return await model;
}
IEnumerable部分生成以下SQL:
SELECT&#34; product.MhpProducts&#34; .MP_MHP_ID,&#34; product.MhpProducts&#34; .MP_PRODUCT_ID,&#34; product.MhpProducts&#34; .MP_G_ORDER,&#34; product.MhpProducts& #34; .G_END_DATE,&#34; product.MhpProducts&#34; .G_INSERT_BY,&#34; product.MhpProducts&#34; .G_INSERT_DATE,&#34; product.MhpProducts&#34; .G_IS_DELETED,&#34;产品.MhPProducts&#34; .G_START_DATE,&#34; product.MhpProducts&#34;。&#34; MP_WEST_CORE._DOMAIN._ENTITIES._WEST_LIFE._MHP_PRODUCT&#34; 来自MHP_PRODUCT&#34; product.MhpProducts&#34; 内部联接 ( SELECT&#34; product0&#34; .TP_ID 来自TREE_PRODUCT&#34; product0&#34; )&#34; t&#34; ON&#34; product.MhpProducts&#34; .MP_PRODUCT_ID =&#34; t&#34; .TP_ID ORDER BY&#34; t&#34; .TP_ID