Linq 编译查询和 int[] 作为参数

发布于 2024-08-16 09:04:01 字数 575 浏览 6 评论 0原文

我正在使用以下 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));

我知道不可能使用序列输入参数进行编译查询,并且在运行时出现“参数不能是序列”错误

在另一篇文章相关中,我看到有一些解决方案,但是我无法理解。

有谁知道使用以数组作为输入参数的编译查询?

如果您这样做,请发布示例。

I'm using the following LINQ to SQL compiled query.

 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));

I know it is not possible to use sequence input paramter for a compiled query and im getting “Parameters cannot be sequences” error when running it.

On another post here related , I saw that there is some solution but I couldn't understand it.

Does anyone know to use complied query with array as input paramter?

Please post example if you do.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浪荡不羁 2024-08-23 09:04:01

就像您引用的帖子一样,它实际上不可能开箱即用。这篇文章还提到创建您自己的查询提供程序,但这会带来一些开销和复杂性,您可能不需要。

这里有几个选项:

  1. 不要使用编译的查询。相反,有一个方法将从数组中的每个项目创建一个 where 子句,从而产生如下所示的结果(伪代码):

    <前><代码>在哪里
    online[0] == u.用户名 ||
    在线[1] == u.用户名||
    ...
    在线[n] == u.用户名

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

  2. 如果您使用的是 SQL Server 2008,请创建一个标量值函数,该函数将采用 表值参数和要再次比较的值。它将返回一个位(以指示该项目是否在表中的值中)。然后通过 LINQ-to-SQL 在数据上下文中公开该函数。从那里,您应该能够为此创建一个 CompiledQuery。请注意,在这种情况下,您应该采用 IEnumerable (假设用户名是字符串类型)而不是数组,因为您可能有多种表示字符串序列的方法,对于 SQL Server 执行此操作,顺序无关紧要。

Like the post that you referenced, it's not really possible out of the box. The post also references creating your own query provider, but it's a bit of overhead and complexity that you probably don't need.

You have a few options here:

  1. Don't use a compiled query. Rather, have a method which will create a where clause from each item in the array resulting in something like this (psuedo-code):

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

    Note that you would have to use expression here to create each OR clause.

  2. If you are using SQL Server 2008, create a scalar valued function which will take a table-valued parameter and a value to compare againt. It will return a bit (to indicate if the item is in the values in the table). Then expose that function through LINQ-to-SQL on your data context. From there, you should be able to create a CompiledQuery for that. Note that in this case, you should take an IEnumerable<string> (assuming username is of type string) instead of an array, just because you might have more than one way of representing a sequence of strings, and to SQL server for this operation, it won't matter what the order is.

天荒地未老 2024-08-23 09:04:01

我发现自己正在做的一种解决方案(针对 MS SQL 2005/2008)。我不确定编写动态 sql 并使用 ExecuteQuery 方法针对数据上下文执行它是否适合所有场景。

例如,如果我有一个无界列表,我试图将其传递给查询来执行包含...

' 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”声明。

希望能帮助别人!

One solution that I have found myself doing (for MS SQL 2005/2008). And I'm not sure if it is appropriate in all scenarios is to just write dynamic sql and execute it against the datacontext using the ExecuteQuery method.

For example, if I have an unbounded list that I am trying to pass to a query to do a contains...

' 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

I would modify this query to create a SQL string to execute against the database directly like so...

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

So barring any syntax errors or bugs that I coded (the above is more or less psuedo code and not tested), the above will generate a table variable in SQL and execute an inner join against the desired table (Individuals in this example) and avoid the use of a "IN" statement.

Hope that helps someone out!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文