我有以下linq,我想将不同的条件传递给where子句,但出现错误:
var rslt = (from t in cr.faultStatAlt
join v in cr.errorCatGroup
on t.m_error_id equals v.m_error_id
join h in cr.masterAlarm on t.m_inv_error_details equals h.pc_group_pattern into ps
from h in ps.DefaultIfEmpty()
join s in cr.MasterDataTurbine on t.m_turbine_id equals s.m_turbine_id
where (whereClause)
group t.error_duration by v.m_error_subgroup_name into k
select new faulttest
{
m_error_subgroup = k.Key,
error_duration = Math.Round(k.Sum() / 3600, 2)
}).ToString();
我想使其动态的条件是:
Func<t_fault_stat_alt, bool> whereClause = t => t.m_date >= dt1 && t.m_date <= dt2 && t.m_grid_loss==true;
答案 0 :(得分:2)
您不能使用查询语法将lambda传递到// before repeats, include first element
printf("Opened Lockers: %d", openedLockers[0]);
// repeat comma, space, element
for (int i = 1; i < 5; i++) {
printf(", %d", openedLockers[i]);
}
// after repeats
printf(".\n");
中-您需要改用方法语法。像
where
说明-
查询语法只是编译器为您提供的快捷方式。整个查询在编译时都使用LINQ方法调用重写。对于 var fltr = (from t in cr.faultStatAlt
join v in cr.errorCatGroup
on t.m_error_id equals v.m_error_id
join h in cr.masterAlarm on t.m_inv_error_details equals h.pc_group_pattern into ps
from h in ps.DefaultIfEmpty()
join s in cr.MasterDataTurbine on t.m_turbine_id equals s.m_turbine_id)
.Where (whereClause);
var rslt = (from t in fltr
group t.error_duration by v.m_error_subgroup_name into k
select new faulttest
{
m_error_subgroup = k.Key,
error_duration = Math.Round(k.Sum() / 3600, 2)
}).ToString();
子句,编译器需要一条语句,其结果为where
-编译器将该语句转换为lambda。
您给了编译器lambda以(bool
开头-它不知道如何将其转换为Func<t_fault_stat_alt, bool>
。
答案 1 :(得分:1)
即使该问题已被标记为正确,我也需要注意一些可能在评论中丢失的重要内容。
如果您使用 EntityFramework (或其他接受Expression
而不是Func
的东西),则需要使用其他类型。
给出以下代码,其中Tag是一个包含int字段Id
(及其对应的列)的随机对象,而cntxt是 EntityFramework DBContext
,您将得到以下两个SQL查询:
Func<Data.Net.Tag, bool> cond = (tag) => tag.Id == 1;
var query = cntxt.Tags.Where(cond);
query.ToArray();
// SELECT "Extent1"."Id", "Extent1"."Name" FROM "public"."Tags" AS "Extent1"
query = cntxt.Tags.Where((tag) => tag.Id == 1);
query.ToArray();
// SELECT "Extent1"."Id", "Extent1"."Name" FROM "public"."Tags" AS "Extent1" WHERE 1 = "Extent1"."Id"
原因是 EntityFramework 使用IQueriable
来实际构建那些SQL查询。
然而,由于IQueryable
也实现了IEnumerable
,由于外观的原因,您可能陷入期望Func
和Expression
具有相同行为的陷阱。如果一个人自己检查方法,则区别会变得更加清晰:
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
要仍然获得相同的行为(过滤器方法),您必须将方法头更改为以下内容:
void MyWhere<T>(..., Expression<Func<T, bool>> cond)
有关此的更多信息,请查看例如:
Why would you use Expression<Func<T>> rather than Func<T>?
或Google C# Expression
:)