c# - 参数 'd' 未绑定(bind)到指定的 LINQ to Entities 查询表达式中

标签 c# linq entity-framework reflection

这是什么错误:

The parameter 'd' was not bound in the specified LINQ to Entities query expression

查看详情:

private static IEnumerable<T> ConnectToDatabase(IQueryable dbSet, ParameterExpression pe, IEnumerable<Expression> expressions,
                string orderby, bool desc)
{
  // expressions = 
    Expression body = null;
    if (expressions.Any())
    {
        foreach (Expression expression in expressions)
        {
            body = ExpressionExtensions.JoinExpressions(body == null, Expression.Or, body, expression);
        }
    }
    if (body == null)
    {
        Expression left = Expression.Property(pe, "ID");
        Expression right = Expression.Constant(-1);
        body = Expression.NotEqual(left, right);
    }
    IQueryable<T> results;
    MethodCallExpression whereCallExpression = Expression.Call(
        typeof(Queryable),
        "Where",
        new[] { dbSet.ElementType },
        dbSet.Expression,
        Expression.Lambda<Func<T, bool>>(body, new[] { pe }));

    var ModelType = typeof(T);
    pe = Expression.Parameter(ModelType, "x");
    var propertyInfoOrderBy = GetPropertyInfo(orderby);
    var propertyAccess = Expression.MakeMemberAccess(pe, propertyInfoOrderBy);
    var orderByExp = Expression.Lambda(propertyAccess, pe);

    MethodCallExpression orderByCallExpression = Expression.Call(
        typeof(Queryable),
        "OrderBy",
        new[] { ModelType, propertyInfoOrderBy.PropertyType },
        whereCallExpression,
        Expression.Quote(orderByExp));

    if (desc)
    {
        MethodCallExpression resultExp = Expression.Call(
            typeof(Queryable),
            "OrderByDescending",
            new[] { ModelType, propertyInfoOrderBy.PropertyType },
            orderByCallExpression,
            Expression.Quote(orderByExp));

        results = dbSet.Provider.CreateQuery<T>(resultExp);
    }
    else
    {
        results = dbSet.Provider.CreateQuery<T>(orderByCallExpression);
    }
    return results.ToList();
}

表达式:

expressions

正文:

body

哪里调用表达式:

where

订单调用表达式:

order

错误:

enter image description here

JN_News 类:

public class JN_News
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string NewsLink { get; set; }
    public DateTime PubDate { get; set; }
    public string ImageLink { get; set; }
    public bool IsDisplay { get; set; }
    public Decimal? Rate { get; set; }
    public int NewsCategories_ID { get; set; }
    public virtual JN_NewsCategories JN_NewsCategories { get; set; }
}

JN_NewsCategories 类:

public class JN_NewsCategories
{
    public int ID { get; set; }
    public string NewsCategoriesFa { get; set; }
    public string NewsCategoriesEn { get; set; }
    public bool IsGetNews { get; set; }
    public virtual ICollection<JN_News> JN_News { get; set; }

    public JN_NewsCategories()
    {
        JN_News = new Collection<JN_News>();
    }
}

更新:

当我删除了以下两个语句时。正常工作:

enter image description here

我所有的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace NewsSiteApk.Data.DynamicSearchLibrary
{
    public static class SearchUsingExpression<T> where T : class
    {
        public static IEnumerable<T> Search(IEnumerable<T> listOfT, string search, string orderBy, bool desc, int pageIndex, int pageSize)
        {
            listOfT = GetListOfData(listOfT, search, orderBy, desc).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            return listOfT;
        }
        public static int GetCount(IEnumerable<T> listOfT, string search)
        {
            listOfT = GetListOfData(listOfT, search, "id", true);
            return listOfT.Count();
        }

        private static IEnumerable<T> GetListOfData(IEnumerable<T> listOfT, string search, string orderBy, bool desc)
        {
            var modelType = typeof(T);
            ParameterExpression pe = Expression.Parameter(modelType, "d");
            var expressions = new List<Expression>();
            if (!string.IsNullOrEmpty(search))
            {
                expressions.AddRange(GetExpressions(modelType.Name, search, pe));
            }
            var connectToDatabase = ConnectToDatabase(listOfT.AsQueryable(), pe, expressions, orderBy, desc);
            return connectToDatabase;
        }


        private static IEnumerable<T> ConnectToDatabase(IQueryable dbSet, ParameterExpression pe, IEnumerable<Expression> expressions,
            string orderby, bool desc)
        {
            Expression body = null;
            if (expressions.Any())
            {
                foreach (Expression expression in expressions)
                {
                    body = ExpressionExtensions.JoinExpressions(body == null, Expression.Or, body, expression);
                }
            }
            if (body == null)
            {
                Expression left = Expression.Property(pe, "ID");
                Expression right = Expression.Constant(-1);
                body = Expression.NotEqual(left, right);
            }
            IQueryable<T> results;
            MethodCallExpression whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new[] { dbSet.ElementType },
                dbSet.Expression,
                Expression.Lambda<Func<T, bool>>(body, new[] { pe }));

            var propertyInfoOrderBy = GetPropertyInfo(orderby);
            var propertyAccess = Expression.MakeMemberAccess(pe, propertyInfoOrderBy);
            var orderByExp = Expression.Lambda(propertyAccess, pe);

            var ModelType = typeof(T);
            MethodCallExpression orderByCallExpression = Expression.Call(
                typeof(Queryable),
                "OrderBy",
                new[] { ModelType, propertyInfoOrderBy.PropertyType },
                whereCallExpression,
                Expression.Quote(orderByExp));

            if (desc)
            {
                MethodCallExpression resultExp = Expression.Call(
                    typeof(Queryable),
                    "OrderByDescending",
                    new[] { ModelType, propertyInfoOrderBy.PropertyType },
                    orderByCallExpression,
                    Expression.Quote(orderByExp));

                results = dbSet.Provider.CreateQuery<T>(resultExp);
            }
            else
            {
                results = dbSet.Provider.CreateQuery<T>(orderByCallExpression);
            }
            return results.ToList();
        }

        private static IEnumerable<Expression> GetExpressions(string modelName, string search, ParameterExpression pe)
        {
            var expressions = new List<Expression>();
            var fieldModels = GetFields(modelName);

            foreach (FieldModel fieldModel in fieldModels)
            {
                IEnumerable<Expression> conditionsWithSubModel;
                if (fieldModel.NameEn.Contains("[]"))
                {
                    conditionsWithSubModel = GetConditionsWithSubModelList(search, fieldModel.NameEn, pe);
                }
                else if (fieldModel.NameEn.Contains("."))
                {
                    conditionsWithSubModel = GetConditionsWithSubModel(search, fieldModel.NameEn);
                }
                else
                {
                    conditionsWithSubModel = GetConditionsWithoutSubModel(search, pe, fieldModel.NameEn);
                }
                if (conditionsWithSubModel != null)
                    expressions.AddRange(conditionsWithSubModel);
            }
            return expressions;
        }


        private static IEnumerable<Expression> GetConditionsWithoutSubModel(string search, ParameterExpression pe,
            string parametr)
        {
            var expressions = new List<Expression>();

            foreach (var splitSeacrh in search.Split(' '))
            {
                Expression left = Expression.Property(pe, parametr);
                Expression right = Expression.Constant(splitSeacrh);
                MethodCallExpression conditionExpression = Expression.Call(left, typeof(string).GetMethod("Contains"),
                    right);
                expressions.Add(conditionExpression);
            }

            return expressions;
        }
        private static IEnumerable<Expression> GetConditionsWithSubModel(string search,
            string parameter)
        {
            //         output.Where(d => d.JN_NewsCategories.NewsCategoriesEn.Contains(""));
            var expressions = new List<Expression>();
            var strings = parameter.Split('$');
            var modelName = strings[0]; // Like : JN_News
            var subModelName = strings[1].Split('.')[0];// Like : JN_NewsCategories
            var subModelField = strings[1].Split('.')[1];// Like : NewsCategoriesEn

            foreach (var splitSeacrh in search.Split(' '))
            {
                Type modelClass = GetModel(modelName);
                Type submodelClass = GetModel(subModelName);
                ParameterExpression peSubModel = Expression.Parameter(modelClass, "d");
                Expression leftSubModel = Expression.Property(peSubModel, modelClass.GetProperty(subModelName));
                Expression ex = Expression.Property(leftSubModel, submodelClass.GetProperty(subModelField));
                Expression rightSubModel = Expression.Constant(splitSeacrh);
                MethodCallExpression conditionExpressionSubModel = Expression.Call(ex,
                    typeof(string).GetMethod("Contains"), rightSubModel);

                expressions.Add(conditionExpressionSubModel);
            }

            return expressions;
        }

        private static IEnumerable<Expression> GetConditionsWithSubModelList(string search, string parameter,
            ParameterExpression peModel)
        {
            parameter = parameter.Replace("[]", string.Empty);

            var expressions = new List<Expression>();
            var subModelName = parameter.Split('.')[0];
            var subModelField = parameter.Split('.')[1];
            foreach (var splitSeacrh in search.Split(' '))
            {
                Type modelClass = GetModel(subModelName);
                var subModelProperty = GetPropertyInfo(subModelName);
                ParameterExpression peSubModel = Expression.Parameter(modelClass, "d");
                Expression leftSubModel = Expression.Property(peSubModel, modelClass.GetProperty(subModelField));
                Expression rightSubModel = Expression.Constant(splitSeacrh);
                MethodCallExpression conditionExpressionSubModel = Expression.Call(leftSubModel,
                    typeof(string).GetMethod("Contains"), rightSubModel);
                LambdaExpression anyLambdaSubModelForModel = Expression.Lambda(conditionExpressionSubModel, peSubModel);
                MethodInfo anyMethodForModel = CreateAnyMethodGeneric(subModelProperty);
                Expression lambedaSubModelForExpressionModel = Expression.Property(peModel, subModelProperty);
                Expression expression = Expression.Call(anyMethodForModel, lambedaSubModelForExpressionModel,
                    anyLambdaSubModelForModel);
                expressions.Add(expression);
            }

            return expressions;
        }

        private static Type GetModel(string name)
        {
            return (typeof(T).Assembly).GetTypes()
                .First(d => string.Equals(d.Name, name, StringComparison.CurrentCultureIgnoreCase));
        }

        private static PropertyInfo GetPropertyInfo(string name)
        {
            return typeof(T).GetProperties().First(d => string.Equals(d.Name, name, StringComparison.CurrentCultureIgnoreCase));
        }

        private static MethodInfo CreateAnyMethodGeneric(PropertyInfo propYekiBeAkhar, string methodName = "Any")
        {
            return
                typeof(Enumerable).GetMethods()
                    .Single(m => m.Name == methodName && m.GetParameters().Length == 2)
                    .MakeGenericMethod(propYekiBeAkhar.PropertyType.GenericTypeArguments[0]);
        }

        private static IEnumerable<FieldModel> GetFields(string modelName)
        {
            var fieldsFactory = new FieldsFactory();
            var fieldModels = fieldsFactory.GetClause(modelName);
            return fieldModels;
        }
    }
}

现场工厂类:

public class FieldsFactory
    {
        public List<FieldModel> GetClause(string modelName)
        {
            var type = typeof(FieldsFactory);
            var methodInfos = type.GetMethod("Get" + modelName + "Fields", BindingFlags.NonPublic | BindingFlags.Instance);
            var listOfFields = (List<FieldModel>)methodInfos.Invoke(this, null);
            return listOfFields;
        }

        private List<FieldModel> GetJN_NewsCategoriesFields()
        {
            var fields = new List<FieldModel>
            {
                new FieldModel
                {
                    NameEn = "NewsCategoriesFa",
                },
                new FieldModel
                {
                    NameEn = "NewsCategoriesEn",
                },
                new FieldModel
                {
                    NameEn = "JN_News[].Title",
                },
                new FieldModel
                {
                    NameEn = "JN_News[].Description",
                }
            };
            return fields;
        }
        private List<FieldModel> GetJN_NewsFields()
        {
            var fields = new List<FieldModel>
            {
                new FieldModel
                {
                    NameEn = "Title",
                },
                new FieldModel
                {
                    NameEn = "JN_News$JN_NewsCategories.NewsCategoriesFa",
                },
                new FieldModel
                {
                    NameEn = "JN_News$JN_NewsCategories.NewsCategoriesEn",
                }
            };
            return fields;
        }
    }

最佳答案

我太棒了。我很高兴。

只是,我替换了下面的方法:

private static IEnumerable<Expression> GetConditionsWithSubModel(string search, ParameterExpression pe,
    string parameter)
{
    //         output.Where(d => d.JN_NewsCategories.NewsCategoriesEn.Contains(""));
    var expressions = new List<Expression>();
    var strings = parameter.Split('$');
    var modelName = strings[0];
    var subModelName = strings[1].Split('.')[0];
    var subModelField = strings[1].Split('.')[1];

    foreach (var splitSeacrh in search.Split(' '))
    {
        Type modelClass = GetModel(modelName);
        Type submodelClass = GetModel(subModelName);
        ParameterExpression peSubModel = Expression.Parameter(modelClass, "d");
        Expression leftSubModel = Expression.Property(peSubModel, modelClass.GetProperty(subModelName));
        Expression ex = Expression.Property(leftSubModel, submodelClass.GetProperty(subModelField));
        Expression rightSubModel = Expression.Constant(splitSeacrh);
        MethodCallExpression conditionExpressionSubModel = Expression.Call(ex,
            typeof(string).GetMethod("Contains"), rightSubModel);

        expressions.Add(conditionExpressionSubModel);
    }

    return expressions;
}

使用以下方法:

private static IEnumerable<Expression> GetConditionsWithSubModel(string search, ParameterExpression pe,
    string parameter)
{
    //         output.Where(d => d.JN_NewsCategories.NewsCategoriesEn.Contains(""));
    var expressions = new List<Expression>();
    var strings = parameter.Split('$');
    var modelName = strings[0];
    var subModelName = strings[1].Split('.')[0];
    var subModelField = strings[1].Split('.')[1];

    foreach (var splitSeacrh in search.Split(' '))
    {
        Type modelClass = GetModel(modelName);
        Type submodelClass = GetModel(subModelName);
        Expression leftSubModel = Expression.Property(pe, modelClass.GetProperty(subModelName));
        Expression ex = Expression.Property(leftSubModel, submodelClass.GetProperty(subModelField));
        Expression rightSubModel = Expression.Constant(splitSeacrh);
        MethodCallExpression conditionExpressionSubModel = Expression.Call(ex,
            typeof(string).GetMethod("Contains"), rightSubModel);

        expressions.Add(conditionExpressionSubModel);
    }

    return expressions;
}

关于c# - 参数 'd' 未绑定(bind)到指定的 LINQ to Entities 查询表达式中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25506689/

相关文章:

c# - 在 EF 中使用 Attach 时,是否可以不覆盖我尚未更新的属性?

asp.net-mvc - 如何在 Entity Framework Code First 中创建运行时计算(未映射)值

c# - 使用 C# 和 Web API 自定义所需属性,并使用带有验证上下文的私有(private)访问修饰符

c# - 用于抑制空列表的 XmlSerialization 的魔法名称

c# - 从列表 Linq 中删除重复的起始名称

c# - 使用 linq 截断文本

entity-framework - 在 EF Power Tools 代码逆向工程中指定架构名称

c# - 如何将 ASP.NET 服务器控件传递给函数?

c# - 自定义 UITableViewCell 宽度问题

.net - 多个后代类型 linq