EF Core 2.0包含具有动态查询的嵌套实体

Gue*_*lla 0 c# entity-framework-core .net-core

我正在使用System.Linq.Dynamic.Core;以下扩展方法通过名称动态访问DbSet并从字符串生成查询。

这是淘汰方法:

namespace Microsoft.EntityFrameworkCore
{
    public static partial class CustomExtensions
    {
        public static IQueryable Query(this DbContext context, string entityName) =>
            context.Query(context.Model.FindEntityType(entityName).ClrType);

        public static IQueryable Query(this DbContext context, Type entityType) =>
            (IQueryable)((IDbSetCache)context).GetOrAddSet(context.GetDependencies().SetSource, entityType);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我访问DbSet的方式:

IQueryable<T> dbSet = (IQueryable<T>)_db.Query(entityName);
Run Code Online (Sandbox Code Playgroud)

这可以正常工作,我可以构建查询,然后创建列表,但是没有嵌套实体加载。似乎IQueryable没有的定义Include()。如果我以常规方式直接访问数据库上下文,但未使用此动态方法,则可以看到包含方法。

如何使用动态方法包括嵌套实体?

Ram*_*yev 9

我有一个解决这个问题的代码。我使用表达式树。

我的实体模型如下:

public class PortfolioTechnology
{
    public int PortfolioId { get; set; }
    public Portfolio Portfolio { get; set; }

    public int TechnologyId { get; set; }
    public Technology Technology { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的主要代码如下:

public SharpListResponse<PortfolioTechnology> GetAll(
    Expression<Func<PortfolioTechnology, bool>> predicate,
    params Expression<Func<PortfolioTechnology,object>>[] includes)
{
    var query = _dbContext.PortfolioTechnology.AsQueryable();

    foreach (var include in includes)
    {
        var memberExpression = include.Body as MemberExpression;

        if (memberExpression != null)
            query = query.Include(memberExpression.Member.Name);
    }

    var result = query.Where(predicate).ToList();

    return new SharpListResponse<PortfolioTechnology>(result);
}
Run Code Online (Sandbox Code Playgroud)

并使用该方法如下:

var list = _unitOfWork.PortfolioTechnologyRepository.GetAll(x => x.PortfolioId == id, 
                                                            y => y.Technology);
Run Code Online (Sandbox Code Playgroud)

如果您想包括多个实体,例如包括投资组合和技术实体,您的代码如下所示:

 var list = _unitOfWork.PortfolioTechnologyRepository.GetAll(x => x.PortfolioId == id, 
                                                             y => y.Technology,
                                                             x => x.Portfolio);
Run Code Online (Sandbox Code Playgroud)

注意:SharpListResponse是包装类。没有它代码也可以工作

SharpListResponse 的更多详细信息:https://www.nuget.org/packages/SharpRequestResponseWrapper/


pro*_*res 5

首先您正在使用的GetOrAddSetIDbSetCache

public interface IDbSetCache
Run Code Online (Sandbox Code Playgroud)

// //摘要://此API支持Entity Framework Core基础结构,//不能直接在您的代码中使用。此API将来可能会更改或删除

IncludeIQueryable<TEntity>类中EntityFrameworkQueryableExtensions的方法Microsoft.EntityFrameworkCore,不是用于IQueryable。您的函数返回IQueryable

我建议您创建如下所示的扩展方法,

        public static IQueryable<T> MyQuery<T>(this DbContext context)
            where T : class
        {
            return context.Set<T>().AsQueryable();
        }
Run Code Online (Sandbox Code Playgroud)

你可以用

  var result = _dbContext.MyQuery<Employee>().Include("Department");
Run Code Online (Sandbox Code Playgroud)

对于动态包含,

    /// <summary>
    /// Query with dynamic Include
    /// </summary>
    /// <typeparam name="T">Entity</typeparam>
    /// <param name="context">dbContext</param>
    /// <param name="includeProperties">includeProperties with ; delimiters</param>
    /// <returns>Constructed query with include properties</returns>
    public static IQueryable<T> MyQueryWithDynamicInclude<T>(this DbContext context, string includeProperties)
       where T : class
    {            
        string[] includes = includeProperties.Split(';');
        var query = context.Set<T>().AsQueryable();

        foreach (string include in includes)
            query = query.Include(include);

        return query;
    }
Run Code Online (Sandbox Code Playgroud)