我希望能够在Linq查询中传递不同的变量,具体取决于字符串是否为空。
string site = null;
int q = a number;
var data = db.tbl_table12345
.Where(site == null
? d => d.stuff_id == org
&& d.Date.Month == q
&& d.Date.Year == year
&& d.Q1 != (int?)null
: d => d.stuff_id == org
&& d.Service == site
&& d.Date.Month == q
&& d.Date.Year == year
&& d.Q1 != (int?)null)
.GroupBy(d => d.Q1)
.Select(d => new
{
q1 = d.Key,
total = d.Count()
});
因此,在上面的示例中site == null
,我们会在没有.Where
参数的情况下执行d.Service == site
搜索。否则,除了查询的其余部分之外,还使用service参数。这可能吗?
答案 0 :(得分:4)
如果要在满足条件时向查询添加额外的过滤器,那么该构造应该在查询本身之外,LINQ很容易做到:
var query = db.tbl_table12345
.Where(d => d.stuff_id == org
&& d.Date.Month == q
&& d.Date.Year == year
&& d.Q1 != (int?)null);
if (site != null)
query = query.Where(d => d.Service == site);
var data = query.GroupBy(d => d.Q1)
.Select(d => new
{
q1 = d.Key,
total = d.Count()
});
答案 1 :(得分:1)
如果三元运算符在lambda“内部”,它应该可以工作。
string site = null;
int q = a number;
var data = db.tbl_table12345
.Where(d => site == null
? d.stuff_id == org
&& d.Date.Month == q
&& d.Date.Year == year
&& d.Q1 != (int?)null
: d.stuff_id == org
&& d.Service == site
&& d.Date.Month == q
&& d.Date.Year == year
&& d.Q1 != (int?)null)
.GroupBy(d => d.Q1)
.Select(d => new
{
q1 = d.Key,
total = d.Count()
});
答案 2 :(得分:1)
分解表达式可以让您更好地可视化您的逻辑。
string site = null;
int month = a number;
Expression<Func<SomeType, bool>> nullExpression =
d => d.stuff_id == org
&& SqlFunctions.DatePart("MONTH", d.Date) == month
&& SqlFunctions.DatePart("YEAR", d.Date) == year
&& d.Q1 != (int?)null;
Expression<Func<SomeType, bool>> notNullExpression =
d => d.stuff_id == org
&& SqlFunctions.DatePart("MONTH", d.Date) == month
&& SqlFunctions.DatePart("YEAR", d.Date) == year
&& d.Q1 != (int?)null
&& d.Service == site;
var expression = site == null ? nullExpression : notNullExpression
var data = db.tbl_table12345
.Where(expression)
.GroupBy(d => d.Q1)
.Select(d => new { q1 = d.Key, total = d.Count() });
或使用表达式树:
var expression = BuildWhere(org, month, year, site);
var data = db.tbl_table12345
.Where(expression)
.GroupBy(d => d.Q1)
.Select(d => new { q1 = d.Key, total = d.Count() });
这是一种方法,可以建立你的Expression<Func<SomeType, bool>
。
public Expression BuildWhere(int org, int month, int year, string service = null)
{
var datePartMethod =
typeof(SqlFunctions)
.GetMethod("DatePart",
new[]
{
typeof(string),
typeof(DateTime?)
});
// Variable d
var variable =
Expression.Variable(typeof(SomeType));
var orgConstant =
Expression.Constant(org);
// d.stuff_id
var stuffId =
Expression.Property(variable, "stuff_id");
// d.stuff_id == org
var stuffIdEquals =
Expression.Equal(stuffId, orgConstant);
// d.Date cast into Nullable DateTime
var date =
Expression.Convert(
Expression.Property(variable, "Date"),
typeof(DateTime?));
var monthPartConstant =
Expression.Constant("MONTH");
// month cast to nullable int
var monthConstant =
Expression.Convert(
Expression.Constant(month),
typeof(int?));
var yearPartConstant =
Expression.Constant("YEAR");
// year cast to nullable int
var yearConstant =
Expression.Convert(
Expression.Constant(year),
typeof(int?));
// SqlFunctions.DatePart("MONTH", d.Date)
var invokeDatePartMonthPart =
Expression.Call(
datePartMethod,
monthPartConstant,
date);
// SqlFunctions.DatePart("YEAR", d.Date)
var invokeDatePartYearPart =
Expression.Call(
datePartMethod,
yearPartConstant,
date);
// SqlFunctions.DatePart("MONTH", d.Date) == month
var dateMonthEquals =
Expression.Equal(
invokeDatePartMonthPart,
monthConstant);
// SqlFunctions.DatePart("MONTH", d.Date) == year
var dateYearEquals =
Expression.Equal(
invokeDatePartYearPart,
yearConstant);
// d.Q1
var q1 = Expression.Property(variable, "Q1");
var nullConstant =
Expression.Constant((int?) null);
// d.Q1 != (int?) null
var q1NotEquals =
Expression.NotEqual(
q1,
nullConstant);
// d.stuff_id == org
// && SqlFunctions.DatePart("MONTH", d.Date) == month
// && SqlFunctions.DatePart("YEAR", d.Date) == year
// && d.Q1 != (int?) null
var andExpression =
Expression.AndAlso(stuffIdEquals,
Expression.AndAlso(dateMonthEquals,
Expression.AndAlso(dateYearEquals,
q1NotEquals)));
// Add d.Service only when not null
if(service != null)
{
// d.Service
var serviceConstant =
Expression.Constant(service);
var serviceProperty =
Expression.Property(
variable,
"Service");
// d.Service == service
var serviceEquals =
Expression.Equal(
serviceProperty,
serviceConstant);
andExpression =
Expression.AndAlso(
andExpression,
serviceEquals);
}
// Creates a lambda to represent the logic
var parameter = Expression.Parameter(typeof(SomeType));
return Expression
.Lambda<Func<SomeType, bool>>(
andExpression,
parameter);
}
答案 3 :(得分:0)
您的语法错误
.Where(d => site == null
? d.stuff_id == org
&& d.Date.Month == q && d.Date.Year == year
&& d.Q1 != (int?)null
: d.stuff_id == org
&& d.Service == site && d.Date.Month == q
&& d.Date.Year == year && d.Q1 != (int?)null)
答案 4 :(得分:0)
从您的代码看起来的方式来看,我认为您正在使用Entity Framework进行查询。如果是这样,那么你不允许d.Date.Month
这样的东西,因为EF不知道如何正确地将它转换成SQL本身。您需要使用SqlFunctions
类(特别是DatePart方法)才能使此查询正常工作。使用@ Servy的解决方案作为开始:
var query = db.tbl_table12345
.Where(d => d.stuff_id == org
&& SqlFunctions.DatePart("MONTH", d.Date) == q
&& SqlFunctions.DatePart("YEAR", d.Date) == year
&& d.Q1 != (int?)null);
if (site != null)
query = query.Where(d => d.Service == site);
var data = query.GroupBy(d => d.Q1)
.Select(d => new
{
q1 = d.Key,
total = d.Count()
});
使用此方法的另一个好理由是上面的所有LINQ子句(Where
,GroupBy
和Select
都使用了延迟执行(请参阅here延迟与立即执行方法的列表),这意味着只有一个查询将被发送到您的数据库以用于最终data
,并且只有当您以某种方式实际使用该变量时才会发送。