试图在 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 语句中返回两个纬度/经度坐标之间的计算距离