代码之家  ›  专栏  ›  技术社区  ›  Football-Is-My-Life

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

  •  4
  • Football-Is-My-Life  · 技术社区  · 11 年前

    此错误是什么:

    参数“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

    其中调用表达式:

    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;
            }
        }
    
    1 回复  |  直到 11 年前
        1
  •  1
  •   John Saunders    11 年前

    我很高兴。我很高兴。

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

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