5

我正在使用 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 等。

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) 调用的需要'上面已经完成了。

提前致谢。

4

1 回答 1

8

以下是我在通用存储库中的操作方式:

    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 包含和 FirstOrDefault 而不是 find 但结果是相同的。

您可以在此处查看我的通用存储库的完整源代码。

您可以通过以下方式调用它:

var entity = myRepository.GetBy(e=>e.Id == 7, /*Includes*/ e=> e.ANavigationProperty, e=>e.AnotherNavProperty);

编辑:

我不再使用通用存储库,而是使用扩展方法即时构建查询。我发现这得到了更好的重用。(请参阅我关于可组合存储库的文章)

于 2013-01-15T19:43:17.937 回答