简体   繁体   English

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

[英]Entity Framework Generic repository including properties through parameter

I have an implementation of a Generic Repository in Entity Framework which I am trying to improve to use the .Include(..) function provided by EF instead of including the navigation properties by string, in order to be able to safely rename properties. 我在Entity Framework中实现了通用存储库的实现,我正在尝试改进该存储库,以使用EF提供的.Include(..)函数,而不是通过字符串包括导航属性,以便能够安全地重命名属性。

Below is my current code: 下面是我当前的代码:

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;
        }
    }

I currently use this in the following way: 我目前以以下方式使用它:

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

My question is: how can I change the method in order to be able to call it in the following way (or similar): 我的问题是:如何更改方法以便能够以以下方式(或类似方式)调用它:

repository.GetAll(
    u => u.Name = "John",
    u => u.OrderBy(x => x.Name),
    u => u.Include(x => x.Address).ThenInclude(x => x.State),
);
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);
}

And this method called there 这个方法叫做

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)));
}

Filter Method Call 过滤方法调用

 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);
            }

I suggest you to keep two methods, one accepting string params and one expression params. 我建议您保留两种方法,一种接受字符串参数,另一种接受表达式参数。 Some of the clients of your repository can work better with the string signature and some of them can work better with expression signature which brings IntelliSense for them. 存储库中的某些客户端可以更好地使用字符串签名,而某些客户端可以更好地使用表达式签名,这为他们带来了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;
}

Make sure you have added using System.Data.Entity; 确保已using System.Data.Entity;添加using System.Data.Entity; .

You can implement the logic for filter and sort the same way. 您可以使用相同的方法来实现过滤器和排序逻辑。 For the string params signature for filter and sort, you can use System.Linq.Dynamic package. 对于用于过滤和排序的字符串参数签名,可以使用System.Linq.Dynamic包。

Example: 例:

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

You can use the params Expression<Func<T, object>>[] includeProperties instead of string parameter 您可以使用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;
        }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM