2009-12-28 2 views
1

Я использую следующий скомпилированный запрос LINQ to SQL.Linq Compiled Queries и int [] как параметр

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

Просто прочитайте глубже и ТОГДА дайте нам знать, когда застрянете. http: //social.msdn.microsoft.com/forums/en-US/linqtosql/thread/08ccbb12-da4f-421a-8912-8fa95ebbead0/ –

+0

Я сделал :(, это действительно сложно, и примеры на самом деле не связаны с простым требованием передачи массива как Параметр – dan

ответ

1

Как и сообщение, на которое вы ссылаетесь, на самом деле это невозможно сделать из коробки. Сообщение также ссылается на создание собственного поставщика запросов, но это немного накладные расходы и сложность, которые вам, вероятно, не нужны.

У вас есть несколько вариантов здесь:

  1. Не используйте скомпилированный запрос. Скорее всего, есть метод, который будет создавать ИНЕКЕ из каждого элемента массива, в результате чего-то вроде этого (псевдо-код):

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

    Обратите внимание, что вы должны использовать выражение здесь, чтобы создать каждый OR пункт.

  2. Если вы используете SQL Server 2008, создайте функцию скалярного значения, которая примет значение table-valued parameter и значение для сравнения againt. Он вернет бит (чтобы указать, находится ли элемент в значениях в таблице). Затем выведите эту функцию через LINQ-to-SQL в контексте данных. Оттуда вы сможете создать для этого CompiledQuery. Обратите внимание, что в этом случае вы должны взять IEnumerable<string> (предполагая, что имя пользователя имеет строку типа) вместо массива, просто потому, что у вас может быть несколько способов представления последовательности строк и на SQL-сервер для этой операции, она выиграла «Неважно, что это за заказ.

+0

thx! Я не мог заставить их работать. 1) если я не использую скомпилированный запрос, у меня вообще нет проблем, я могу просто передать параметр int [] в качестве параметра. возможно, я пропустил понимание того, что вы имели в виду. 2) Я читаю о табличном значении, но я думаю, что я ошибаюсь. Я создал скалярную функцию, которая получает параметр table-value, но что он возвращает? – dan

+0

@dan 1) Если вы вообще не используете скомпилированный запрос, вы все равно не можете использовать Contains. Вы должны разделить запрос на несколько операторов OR. 2) Скалярная функция с параметром table value будет возвращать бит, который равен 0, если элемент не содержится в таблице, в которую вы проходите, 1, если это так. – casperOne

1

Одно из решений, которое я нашел (для MS SQL 2005/2008). И я не уверен, что во всех сценариях уместно просто написать динамический sql и выполнить его против datacontext с помощью метода 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».

Надеюсь, что кто-то поможет!