实体框架通用存储库,包括通过参数

时间:2018-12-28 22:37:43

标签: c# entity-framework .net-core

我在Entity Framework中实现了一个通用存储库,我正在尝试改进该存储库以使用EF提供的.Include(..)函数,而不是通过字符串包括导航属性,以便能够安全地重命名属性。

下面是我当前的代码:

public IQueryable<T> GetAll(
        Expression<Func<T, bool>> filter = null,
        Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<T> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query);
        }
        else
        {
            return query;
        }
    }

我目前通过以下方式使用它:

repository.GetAll(
    u => u.Name = "John",
    u => u.OrderBy(x => x.Name),
    "Address.State",
);

我的问题是:如何更改方法以便能够以以下方式(或类似方式)调用它:

repository.GetAll(
    u => u.Name = "John",
    u => u.OrderBy(x => x.Name),
    u => u.Include(x => x.Address).ThenInclude(x => x.State),
);

3 个答案:

答案 0 :(得分:2)

protected internal IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate, params Expression<Func<TEntity, object>>[] includeProperties)
{
    var query = RetrieveQuery();

    if (predicate != null)
    {
        query = query.Where(predicate).AsQueryable();
    }

    if (includeProperties != null)
    {
        query = _queryableUnitOfWork.ApplyIncludesOnQuery(query, includeProperties);
    }

    return (query);
}

这个方法在那里叫

public IQueryable<TEntity> ApplyIncludesOnQuery<TEntity>(IQueryable<TEntity> query, params Expression<Func<TEntity, object>>[] includeProperties) where TEntity : class, IEntity
{
    // Return Applied Includes query
    return (includeProperties.Aggregate(query, (current, include) => current.Include(include)));
}

过滤方法调用

 public IEnumerable<ShowStockProductDto> GetActiveShowStockProductListByProduct(int productId)
            {
                var foundedPStockroducts = Filter(
                    ent => ent.ProductId == productId && ent.IsActive,
                    ent => ent.StockProductPrices,
                    ent => ent.StockProductDepots,
                    ent => ent.StockProductSpecificationValues,
                    ent => ent.StockProductSpecificationValues.Select(spsv => spsv.SpecificationValue)
                    );

                // Map foundedPStockroducts to showStockProductList
                var showStockProductList = TypeAdapterFactory.Adapter.Adapt<IEnumerable<ShowStockProductDto>>(foundedPStockroducts).ToList();

                return (showStockProductList);
            }

答案 1 :(得分:2)

我建议您保留两种方法,一种接受字符串参数,一种接受表达式参数。存储库中的某些客户端可以更好地使用字符串签名,而某些客户端可以更好地使用表达式签名,这为他们带来了IntelliSense。

public IQueryable<T> GetAll(params string[] including)
{
    var query = dbSet.AsQueryable();
    if (including != null)
        including.ToList().ForEach(include =>
        {
            if (!string.IsNullOrEmpty(include))
                query = query.Include(include);
        });
    return query;
}

public IQueryable<T> GetAll(params Expression<Func<T, object>>[] including)
{
    var query = dbSet.AsQueryable();
    if (including != null)
        including.ToList().ForEach(include =>
        {
            if (include != null)
                query = query.Include(include);
        });
    return query;
}

确保已添加using System.Data.Entity;

您可以以相同的方式实现过滤器和排序的逻辑。对于过滤和排序的字符串参数签名,可以使用System.Linq.Dynamic包。

示例:

var result1 = schoolRepository.GetAll("Students", "Teachers");
var result2 = schoolRepository.GetAll(x=>x.Students, x=>x.Teachers);

答案 2 :(得分:1)

您可以使用params Expression<Func<T, object>>[] includeProperties代替字符串参数

public IQueryable<T> GetAll(
    Expression<Func<T, bool>> filter = null,
    Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
    params Expression<Func<T, object>>[] includeProperties)
{
    IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties)
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query);
        }
        else
        {
            return query;
        }
}