林克 .其中()问题“无法确定条件表达式的类型”
本文关键字:表达式 条件 类型 无法确定 其中 问题 林克 | 更新日期: 2023-09-27 18:37:26
我希望能够在 Linq 查询中传递不同的变量,具体取决于字符串是否为 null。
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
,那么我们在没有 d.Service == site
参数的情况下执行.Where
搜索。否则,除了查询的其余部分外,还会使用服务参数。这可能吗?
如果要
在满足条件时向查询添加其他筛选器,则该构造应位于查询本身之外,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()
});
如果三元运算符"在"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()
});
分解表达式将使您更好地可视化逻辑。
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);
}
从您的代码外观来看,在我看来,您正在使用实体框架进行查询。如果是这样,则不允许使用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
)都采用延迟执行(有关延迟执行方法与立即执行方法的列表,请参见此处),这意味着只有一个查询将发送到您的数据库以进行最终data
,并且仅在您以某种方式实际使用该变量时。
你的语法是错误的
.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)