参数' d'未绑定在指定的LINQ to Entities查询表达式中

时间:2014-08-26 13:10:45

标签: c# linq entity-framework reflection

这是什么错误:

  

参数“d”未绑定在指定的LINQ to Entities中   查询表达式

查看详情:

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

whereCallExpression:

where

orderByCallExpression:

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

1 个答案:

答案 0 :(得分:1)

我fooooooooooound。我很开心。

只是,我替换了以下方法:

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