简体   繁体   English

无法转换func类型 <T,bool> 布尔

[英]can not convert type func<T,bool> to bool

I have the following linq which i want to pass different conditions to the where clause,but i get error: 我有以下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();

the condition i want to make it dynamic is : 我想使其动态的条件是:

 Func<t_fault_stat_alt, bool> whereClause = t => t.m_date >= dt1 && t.m_date <= dt2 && t.m_grid_loss==true;

You can't pass a lambda into where in query syntax - you'll need to use method syntax instead. 你可以不通过拉姆达到where查询语法-你需要使用方法的语法来代替。 Something like 就像是

   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();

Explanation - 说明-

Query syntax is just a shortcut the compiler provides for you. 查询语法只是编译器为您提供的快捷方式。 The entire query is rewritten using LINQ method calls when it's compiled. 整个查询在编译时都使用LINQ方法调用重写。 For where clauses, the compiler requires a statement which evaluates to bool - the compiler converts that statement into a lambda. 对于where子句,编译器需要一条计算为bool的语句-编译器将该语句转换为lambda。

You gave the compiler a lambda to start with ( Func<t_fault_stat_alt, bool> ) - it doesn't know how to convert that to a bool . 您给了编译器lambda以( Func<t_fault_stat_alt, bool>Func<t_fault_stat_alt, bool> -它不知道如何将其转换为bool

Even though the question already has been marked as correct, i need to note something important that may get lost in the comments. 即使该问题已被标记为正确,我也需要注意一些可能在注释中丢失的重要内容。

If you use EntityFramework (or anything else that is accepting Expression rather then Func ), you need to use different types. 如果使用EntityFramework (或其他任何接受Expression而不是Func ),则需要使用其他类型。

Given the folloging code where Tag is a random object containing the int field Id (+ its corresponding column) and cntxt is the EntityFramework DBContext , you would yield the following two SQL queries: 给定以下代码,其中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"

Reason being that EntityFramework is using IQueriable to actually build those SQL queries. 原因是EntityFramework使用IQueriable实际构建了这些SQL查询。 Due to IQueryable also implementing IEnumerable however, you may fall into the trap of expecting the same behavior for Func and Expression due to the looks. 由于IQueryable也实现了IEnumerable ,因此由于外观的原因,您可能陷入期望FuncExpression具有相同行为的陷阱。 If one actually checks the methods themself, the difference gets clearer: 如果实际上自己检查方法,则区别会变得更加清晰:

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

To still get the same behavior (Filter-Method), you have to change the method head to something like this: 为了仍然获得相同的行为(Filter-Method),您必须将方法头更改为如下所示:

void MyWhere<T>(..., Expression<Func<T, bool>> cond)

For more on this, check out eg.: Why would you use Expression<Func<T>> rather than Func<T>? 有关更多信息,请查看例如: 为什么要使用Expression <Func <T >>而不是Func <T>? or google C# Expression :) 或google C# Expression :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM