我正在使用以下LINQ to SQL编译查询。
private static Func<MyDataContext, int[], int> MainSearchQuery =
CompiledQuery.Compile((MyDataContext db, int[] online ) =>
(from u in db.Users where online.Contains(u.username)
select u));
我知道不可能对编译的查询使用序列输入参数,并且在运行时“参数不能是序列”错误。
在另一篇帖子related上,我看到有一些解决方案,但我无法理解。
有没有人知道使用带有数组的编译查询作为输入参数?
如果你这样做,请发帖。
答案 0 :(得分:1)
就像你引用的帖子一样,开箱即用并不是真的可行。该帖子还引用了创建自己的查询提供程序,但这可能是您可能不需要的开销和复杂性。
你有几个选择:
不要使用已编译的查询。相反,有一个方法将从数组中的每个项创建一个where子句,从而得到类似这样的东西(伪代码):
where
online[0] == u.username ||
online[1] == u.username ||
...
online[n] == u.username
请注意,您必须在此处使用表达式来创建每个OR子句。
如果您使用的是SQL Server 2008,请创建一个标量值函数,该函数将使用table-valued parameter和值来进行比较。它将返回一点(表示该项是否在表中的值中)。然后通过数据上下文中的LINQ-to-SQL公开该函数。从那里,您应该能够为此创建CompiledQuery。请注意,在这种情况下,您应该使用IEnumerable<string>
(假设用户名是string类型)而不是数组,只是因为您可能有多种表示字符串序列的方法,而对于SQL服务器操作,订单是什么并不重要。
答案 1 :(得分:1)
我发现自己正在做的一个解决方案(对于MS SQL 2005/2008)。而且我不确定在所有场景中是否合适只是编写动态sql并使用ExecuteQuery方法对datacontext执行它。
例如,如果我有一个无限制的列表,我试图传递给查询来执行包含...
' Mock a list of values
Dim ids as New List(of Integer)
ids.Add(1)
ids.Add(2)
' ....
ids.Add(1234)
Dim indivs = (From c In context.Individuals _
Where ids.Contains(c.Id) _
Select c).ToList
我会修改此查询以创建一个SQL字符串,直接对数据库执行,如此...
Dim str As New Text.StringBuilder("")
Dim declareStmt as string = "declare @ids table (indivId int) " & vbcrlf)
For i As Integer = 0 To ids.Count - 1
str.Append("select " & ids(i).ToString() & " & vbcrlf)
If i < ids.Count Then
str.Append("union " & vbcrlf)
End If
Next
Dim selStatement As String = "select * From " & context.Mapping.GetTable(GetType(Individuals)).TableName & _
" indiv " & vbcrlf & _
" inner join @ids ids on indiv.id = ids.id"
Dim query = declareStmt & str.ToString & selStatement
Dim result = context.ExecuteQuery(of Individual)(query).ToList
除非我编码的任何语法错误或错误(上面是或多或少的伪代码而未经过测试),上面将在SQL中生成一个表变量并对所需的表执行内部联接(本例中的个人)并避免使用“IN”语句。
希望能帮助别人!