Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带有where子句的groupby的表达式树,然后选择_C#_Entity Framework_Linq_Lambda - Fatal编程技术网

C# 带有where子句的groupby的表达式树,然后选择

C# 带有where子句的groupby的表达式树,然后选择,c#,entity-framework,linq,lambda,C#,Entity Framework,Linq,Lambda,从UI中,动态列作为API中的参数出现,并且基于该参数,我必须从数据库中获取数据。 示例:在下面的代码中,基于列if condition linq query正在执行。现在,我想使它成为通用的,以便在将来出现新的列条件时使用它 public List<string> GetFilteredTypeAhead(string searchText,string searchForRole,int fiscalyear,int fiscalPeriod) { if (se

从UI中,动态列作为API中的参数出现,并且基于该参数,我必须从数据库中获取数据。 示例:在下面的代码中,基于列if condition linq query正在执行。现在,我想使它成为通用的,以便在将来出现新的列条件时使用它

public List<string> GetFilteredTypeAhead(string searchText,string searchForRole,int fiscalyear,int fiscalPeriod)
        {
 if (searchForRole == "column1")
            {
                var accounts = (from a in _context.Account
                                where a.column1.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear ==fiscalyear
                                group a.column1 by a.column2 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if(searchForRole == "column2")
            {
                var accounts = (from a in _context.Account
                                where a.column2.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear
                                group a.column2 by a.column2 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if (searchForRole == "column3")
            {
                var accounts = (from a in _context.Account
                                where a.column3.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear
                                group a.column3 by a.column3 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if (searchForRole == "column4")
            {
                var accounts = (from a in _context.Account
                                where a.column4.StartsWith(searchText) && a.FiscalPeriod.Equals(fiscalPeriod) && a.FiscalYear.Equals(fiscalyear)
                                group a.column4 by a.column4 into g
                                select g.Key).ToList();
                return accounts;
            }
            else
            {
                return new List<string>();
            }
        }
public List GetFilteredTypeAhead(字符串searchText、字符串searchForRole、int fiscalyear、int fiscalPeriod)
{
如果(searchForRole==“column1”)
{
var accounts=(来自一个in_context.Account
其中,a.column1.StartsWith(searchText)和&a.FiscalPeriod==FiscalPeriod和&a.FiscalYear==FiscalYear
将a.column1由a.column2分组为g
选择g.Key).ToList();
归还账户;
}
else if(searchForRole==“column2”)
{
var accounts=(来自一个in_context.Account
其中,a.column2.StartsWith(searchText)和&a.FiscalPeriod==FiscalPeriod和&a.FiscalYear==FiscalYear
将a.column2由a.column2分组为g
选择g.Key).ToList();
归还账户;
}
else if(searchForRole==“column3”)
{
var accounts=(来自一个in_context.Account
其中,a.column3.StartsWith(searchText)和&a.FiscalPeriod==FiscalPeriod和&a.FiscalYear==FiscalYear
a.column3组由a.column3组分为g组
选择g.Key).ToList();
归还账户;
}
else if(searchForRole==“column4”)
{
var accounts=(来自一个in_context.Account
其中a.column4.StartsWith(searchText)和&a.FiscalPeriod.Equals(FiscalPeriod)和&a.FiscalYear.Equals(FiscalYear)
将a.column4按a.column4分组为g
选择g.Key).ToList();
归还账户;
}
其他的
{
返回新列表();
}
}
将其转换为泛型。我创建了一个表达式树

static IQueryable<T> ConvertToExpression<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo, int fiscalyear, int fiscalPeriod)
        {
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
            ConstantExpression c = Expression.Constant(propertyValue, typeof(string));
            MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
            Expression call = Expression.Call(m, mi, c);

            PropertyInfo propertyInfoFiscalPeriod = typeof(T).GetProperty("FiscalPeriod");
            MemberExpression memberPropertyFiscalPeriod = Expression.Property(e, propertyInfoFiscalPeriod);
            ConstantExpression right = Expression.Constant(fiscalPeriod);
            Expression equalsFiscalPeriod = Expression.Equal(memberPropertyFiscalPeriod, Expression.Convert(right, typeof(Int16)));

            PropertyInfo propertyInfoFiscalYear = typeof(T).GetProperty("FiscalYear");
            MemberExpression memberPropertyFiscalYear = Expression.Property(e, propertyInfoFiscalYear);
            right = Expression.Constant(fiscalyear);
            Expression equalsFiscalYear = Expression.Equal(memberPropertyFiscalYear, Expression.Convert(right, typeof(Int16)));

            Expression combineExpression = Expression.And(equalsFiscalPeriod, equalsFiscalYear);

            Expression predicateBody = Expression.And(call, combineExpression);

            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(predicateBody, e);
            return query.Where(lambda);
        }

静态IQueryable ConvertToExpression(IQueryable查询、字符串propertyValue、PropertyInfo PropertyInfo、int fiscalyear、int fiscalPeriod)
{
ParameterExpression e=表达式。参数(类型(T),“e”);
MemberExpression m=Expression.MakeMemberAccess(e,propertyInfo);
ConstantExpression c=表达式.常量(propertyValue,typeof(string));
MethodInfo mi=typeof(string).GetMethod(“StartsWith”,新类型[]{typeof(string)});
表达式调用=表达式调用(m,mi,c);
PropertyInfo PropertyInfo FiscalPeriod=typeof(T).GetProperty(“FiscalPeriod”);
MemberExpression memberPropertyFiscalPeriod=Expression.Property(e,PropertyInFofFiscalPeriod);
ConstantExpression right=表达式常数(财政期间);
Expression equalsFiscalPeriod=Expression.Equal(memberPropertyFiscalPeriod,Expression.Convert(右,typeof(Int16));
PropertyInfo propertyinfofoffiscalyear=typeof(T).GetProperty(“FiscalYear”);
MemberExpression memberPropertyFiscalYear=Expression.Property(e,propertyInfoFiscalYear);
右=表达式常数(财政年度);
Expression equalsFiscalYear=Expression.Equal(memberPropertyFiscalYear,Expression.Convert(右,typeof(Int16));
表达式combineExpression=Expression.And(equalsFiscalPeriod,equalsFiscalYear);
Expression-predicateBody=Expression.And(调用,组合表达式);
表达式lambda=Expression.lambda(谓词库,e);
返回查询.Where(lambda);
}
我用下面的代码来称呼它 “searchForRole”作为参数出现在“column1”、“column2”等中


PropertyInfo PropertyInfo=typeof(Account).GetProperty(searchForRole);
IQueryable查询=_context.Account;
query=ConvertToExpression(查询、搜索文本、属性信息、财政年度、财政期间);
var list=query.ToList();

现在这是工作正常,但结果有重复记录。我希望在传递的参数列上有一些不同的或分组依据。简单地说,我想删除if条件并使我的搜索方法通用。请帮助。

这是可能的,但我认为最好将动态部分保持在最低限度,并尽可能使用C#编译时安全性

正在讨论的示例查询

var accounts = (from a in _context.Account
                where a.column1.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear ==fiscalyear
                group a.column1 by a.column1 into g
                select g.Key).ToList();
可以重写如下

var accounts = _context.Account
    .Where(a => a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear)
    .Select(a => a.column1)
    .Where(c => c.StartsWith(searchText))
    .Distinct()
    .ToList();
如您所见,唯一的动态部分是
a=>a.column1
类型的
Expression
。因此,您只需要这样一种方法:

static Expression<Func<T, M>> MemberSelector<T>(string name)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = Expression.PropertyOrField(name);
    return Expression.Lambda<Func<T, M>>(body, parameter);
}

。选择(成员选择器(searchForRole))

动态查询的最佳方法是使用System.Linq.Dynamic library,您可以从NugetHanks中找到它。看起来很有效。只是想检查一下expression-expression中的func返回类型“M”,我们是否可以将其转换为自定义返回数据,如``public class FilterDto{public string Value{get;set;}public string Text{get;set;}}}``然后转换为toList(),这样的要求很好提前提供,因为它们可能需要完全不同的解决方案。不清楚DTO的
Value
Text
属性是什么。注释空间也是有限的。考虑一下另一个问题,包括你到底需要什么。干杯
static Expression<Func<T, M>> MemberSelector<T>(string name)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = Expression.PropertyOrField(name);
    return Expression.Lambda<Func<T, M>>(body, parameter);
}
.Select(a => a.column1)
.Select(MemberSelector<Account, string>(searchForRole))