我正在使用Entity Framework 5并且有一个通用的存储库,其中有几个方法,如下面的两个Get()方法:
public TEntity GetById(int id)
{
return DbSet.Find(id);
}
public TEntity Get(
Expression<Func<TEntity, bool>> filter = null,
IEnumerable<string> includePaths = null)
{
IQueryable<TEntity> query = DbSet;
if (filter != null)
{
query = query.Where(filter);
}
if (includePaths != null)
{
query = includePaths.Aggregate(query, (current, includePath) => current.Include(includePath));
}
return query.SingleOrDefault();
}
这些都非常有用,但是当我想要进行稍微复杂的GetById()调用并同时检索一些实体引用时,如下所示:
var user = _userRepository.GetById(
id,
new List<string> { "Roles", "Invoices" });
我最终必须为每个实体推出特定于实体的(非通用的)GetById(id,includes)调用,以便我可以访问lambda中的特定Id字段,即UserId或InvoiceId等。< / p>
public User GetById(
int id,
IEnumerable<string> includes)
{
return Get(
(u => u.UserId == id),
includes);
}
似乎我不能凭借我的平均EF技能,研究如何以通用方式将DbSet.Find(id)的优点与.Include()调用结合起来。
所以问题是 - 有没有办法编写一个通用的EF方法,我可以通过它的id来获取一个实体并包含一些引用,反过来又不需要编写特定于实体的GetById(id,includes)像我上面那样的电话。
提前致谢。
答案 0 :(得分:6)
以下是我在通用存储库中的表现:
public T GetBy(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes)
{
var result = GetAll();
if (includes.Any())
{
foreach (var include in includes)
{
result = result.Include(include);
}
}
return result.FirstOrDefault(predicate);
}
注意这是使用lambda includes和FirstOrDefault而不是find但结果是一样的。
您可以查看我的通用存储库here的完整来源。
您可以通过以下方式致电:
var entity = myRepository.GetBy(e=>e.Id == 7, /*Includes*/ e=> e.ANavigationProperty, e=>e.AnotherNavProperty);
修改强>
我不再使用通用存储库,而是使用扩展方法动态构建查询。我发现这可以更好地重用。 (参见Composable Repositories上的文章)