Как избежать ограничения 2100 параметров в LINQ to SQL - PullRequest
7 голосов
/ 25 мая 2011

В проекте, над которым я сейчас работаю, мне нужно получить доступ к 2 базам данных в LINQ следующим образом:

  1. Я получаю список всех номеров поездок в указанном диапазоне дат из DB1 и сохраняю его в виде списка «длинных» значений

  2. Я выполняю обширный запрос со множеством объединений в DB2, но смотрю только на поездки, в которых номер поездки включен в приведенный выше список.

Проблема в том, что список отключений из DB1 часто возвращает более 2100 элементов - и я, конечно, достигаю предела 2100 параметров в SQL, что приводит к сбою моего второго запроса. Я искал способы обойти это, например, описал здесь , но это привело к существенному изменению моего запроса на LINQ-to-Objects, что вызывает много проблем с моими объединениями

Есть ли какие-либо другие обходные пути, которые я могу сделать?

Ответы [ 3 ]

5 голосов
/ 25 мая 2011

поскольку LINQ-to-SQL может вызывать хранимые процессы, вы можете

  • иметь сохраненный процесс, который принимает массив в качестве входных данных, а затем помещает значения во временную таблицу для объединения на
  • аналогично, взяв строку, которая хранится в хранимой процедуре

Или загрузите все значения во временную таблицу самостоятельно и присоединитесь к этой таблице.

Однако, возможно, вам следует пересмотретьпроблема:

  • Сервер Sql можно настроить так, чтобы он разрешал запросы к таблицам в других базах данных (включая oracle), если это разрешено, это может быть вариантом для вас.
  • Не могли бы выкакая-нибудь система репликации для обновления таблицы номеров командировок в DB2?
2 голосов
/ 25 мая 2011

Не уверен, поможет ли это, но у меня была похожая проблема для одноразового запроса, который я писал в LinqPad и в итоге определил и использовал временную таблицу, подобную этой.

[Table(Name="#TmpTable1")]
public class TmpRecord
{
    [Column(DbType="Int", IsPrimaryKey=true, UpdateCheck=UpdateCheck.Never)]
    public int? Value { get; set; }         
}

public Table<TmpRecord> TmpRecords
{
    get { return base.GetTable<TmpRecord>(); }
}

public void DropTable<T>()
{
    ExecuteCommand( "DROP TABLE " + Mapping.GetTable(typeof(T)).TableName  );
}

public void CreateTable<T>()
{
   ExecuteCommand(
    typeof(DataContext)
    .Assembly
    .GetType("System.Data.Linq.SqlClient.SqlBuilder")
    .InvokeMember("GetCreateTableCommand", 
      BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod
     , null, null, new[] { Mapping.GetTable(typeof(T)) } ) as string
    );      
}

Использованиечто-то вроде

void Main()
{
    List<int> ids = .... 

    this.Connection.Open();
    // Note, if the connection is not opened here, the temporary table  
    // will be created but then dropped immediately.

    CreateTable<TmpRecord>();    
    foreach(var id in ids)
        TmpRecords.InsertOnSubmit( new TmpRecord() { Value = id}) ;
    SubmitChanges();

    var list1 = (from r in CustomerTransaction 
        join tt in TmpRecords on r.CustomerID equals tt.Value 
        where ....
        select r).ToList();

     DropTable<TmpRecord>();    
     this.Connection.Close();    

}

В моем случае во временной таблице был только один столбец типа int, но вы должны иметь возможность определять любой тип столбца (столбцов), который вы хотите (до тех пор, покау вас есть первичный ключ).

1 голос
/ 25 мая 2011

Вы можете разделить свой запрос или использовать временную таблицу в базе данных2, заполненную результатами из базы данных1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...