Linq Compiled Queries和int []作为参数

时间:2009-12-28 17:49:42

标签: linq linq-to-sql compiled compiled-query

我正在使用以下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上,我看到有一些解决方案,但我无法理解。

有没有人知道使用带有数组的编译查询作为输入参数?

如果你这样做,请发帖。

2 个答案:

答案 0 :(得分:1)

就像你引用的帖子一样,开箱即用并不是真的可行。该帖子还引用了创建自己的查询提供程序,但这可能是您可能不需要的开销和复杂性。

你有几个选择:

  1. 不要使用已编译的查询。相反,有一个方法将从数组中的每个项创建一个where子句,从而得到类似这样的东西(伪代码):

    where 
        online[0] == u.username ||
        online[1] == u.username ||
        ...
        online[n] == u.username
    

    请注意,您必须在此处使用表达式来创建每个OR子句。

  2. 如果您使用的是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”语句。

希望能帮助别人!