【问题标题】:trying to call a method in the where of a linq statment试图在 linq 语句的 where 中调用方法
【发布时间】: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 表达式。我已经用信息和链接更新了我的答案。

标签: c# .net linq linq-to-sql


【解决方案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
                      };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多