试图在 linq 语句的 where 中调用方法

Posted

技术标签:

【中文标题】试图在 linq 语句的 where 中调用方法【英文标题】:trying to call a method in the where of a linq statment 【发布时间】:2012-01-11 09:10:31 【问题描述】:

下面是我正在使用的代码,但它会回复

方法 'Boolean isUser(System.String)' 不支持对 SQL 的转换。

有什么帮助吗?顺便说一句,我正在使用 linq to SQL 数据源

public void dataBind()

    using (var gp = new GreatPlainsDataContext())
    
        var emp = from x in gp.Employees
                  let k = isUser(x.ID)
                  where x.ActivtyStatus == 0
                  && isUser(x.ID) != false
                  orderby x.ID
                  select new
                  
                      ID = x.ID,
                      Name = x.FirstName + " " + x.MiddleName
                  ;
        ListView1.DataSource = emp;
        ListView1.DataBind();
    


public static bool isUser(string ID)

    int temp;
    bool x = int.TryParse(ID, out temp);
    return x;

我找到了一个解决方案,可以将第一个查询的结果作为对象进行查询,但这很好,因为我将通过我的数据两次。


按照安德斯·阿贝尔的建议,在使用类似之后最终工作的更新代码

public void dataBind()
    
        using (var gp = new GreatPlainsDataContext())
        
            var emp = from x in gp.Employees
                      where x.ActivtyStatus == 0
                      && SqlMethods.Like(x.ID, "[0-9]%")
                      orderby x.ID
                      select new
                      
                          ID = x.ID,
                          Name = x.FirstName + " " + x.MiddleName
                      ;
            ListView1.DataSource = emp;
            ListView1.DataBind();
        
    

【问题讨论】:

Employees.ID 的可能值是什么,为什么可解析为 int 的字符串意味着员工是用户? @spender 关于用户将拥有像“11064”这样的 id 的部分将拥有“oss”。关于我来的原因以及系统是在大平原上建立的:( 遗留系统诅咒一旦获得收益。如果检查字段中是否只有数字就足够了,您可以使用 LIKE 表达式。我已经用信息和链接更新了我的答案。 【参考方案1】:

Linq-to-sql 将查询转换为 SQL。它只知道如何翻译一组有限的内置函数。您必须重写查询以不包含您自己的函数。

可以在MSDN 找到 linq-to-sql 支持的函数和运算符的完整列表。

您可以使用SqlMethods.Like() 来检查该字段是否仅包含数字。示例见T-SQL IsNumeric() and Linq-to-SQL。

【讨论】:

使用IsNumeric 在给定链接上+1 UDF 可能是这种情况下的最佳解决方案。如果它经常使用视图或计算列可能在这里使用。【参考方案2】:

您遇到的问题是,由于查询需要在数据库上运行,您只能使用可以在数据库上运行的东西,isUser 方法中的 C# 代码无法在数据库上运行.

您必须在不使用该功能的情况下重新编写它。也许您有一个表格,按您可以加入的 ID 列出用户?

【讨论】:

【参考方案3】:

你会更容易查询对你有效的ID例如 where ID > 0,恢复结果,然后在结果集合上执行你想要的假设过滤器

isUser(x.ID)

因为,我想,它以某种方式执行更复杂的验证。

重要的是,来自数据库的结果尽可能少,以避免数据传输延迟。

【讨论】:

【参考方案4】:

您可以调用此代码:

var emp = from x in gp.Employees
                  where x.ActivtyStatus == 0
                  orderby x.ID

并获得有效结果,因为每个 linq 表达式都可以通过 linq to sql 应用于Employees。然后,您可以将 emp 转换为列表或数组,并使用您的方法 isUser 过滤集合。

【讨论】:

【参考方案5】:

作为替代解决方案,您可以在gp.isUser(x.ID) 等LINQ 查询中内联调用任何sql UDF(用户定义函数),因此您可以将此函数isUser 定义为SQL UDF,如下所示:

 CREATE FUNCTION isUser(@id int)
 RETURNS bit;
 AS
 BEGIN
    if exists(select * from Users where userId = @id)
    begin 
          return 1; --true the user exists;
    else 
          return 0; --false doesn't exist;
    end
 end

然后您必须define this UDF in your .DBML file 包含其他表和过程定义映射。然后你可以在你的 LINQ 查询中Call it or any other UDF function inline 像这样:

var emp = from x in gp.Employees
              let k = gp.isUser(x.ID)
              where x.ActivtyStatus == 0
              && gp.isUser(x.ID) != 1
              orderby x.ID
              select new
              
                  ID = x.ID,
                  Name = x.FirstName + " " + x.MiddleName + " " + x.LastName
              ;

【讨论】:

以上是关于试图在 linq 语句的 where 中调用方法的主要内容,如果未能解决你的问题,请参考以下文章

具有可为空对象属性的 Linq“where”条件导致“调用非静态方法需要一个目标”

C# 在 Linq 查询 WHERE 语句中返回两个纬度/经度坐标之间的计算距离

c# linq语句的where该怎样动态赋值?

是否可以在对 Where 的调用中调用命名方法?

Linq 错误:“where”条件无效。实体成员正在调用无效的属性或方法

linq之延迟加载和即时加载+标准查询运算符