Как заставить linq использовать sql правильный тип данных для параметров sql?

У меня есть ситуация, когда определенный запрос linq, который выполняется для таблицы с многомиллионными строками, занимает слишком много времени. Я проанализировал вывод запроса linq и обнаружил, что он создает параметры для предложения where с использованием неправильного типа данных. Например, одно поле было определено в базе данных как Char (12), но параметр, с которым оно сравнивалось, был объявлен как NVarChar (12). После того, как я изменил запрос на использование Char вместо NVarChar, он работал менее чем за секунду, как и должен. Есть ли способ заставить linq to sql использовать правильный тип данных, как определено в файле .dbml для этого столбца? Я дважды проверил и определил его как DbType = "Char (12)" в файле контекста данных .dbml.


person Jason    schedule 04.11.2009    source источник
comment
Интересно, есть ли у вас плохой кешированный план выполнения, потому что nvarchar (12) и char (12) не должны иметь большого значения. По крайней мере, я не думаю, что должны.   -  person Jack Marchetti    schedule 05.11.2009
comment
После небольшого тестирования, это действительно так. Я очищал кеш запросов перед каждым запуском, и он увеличился с 4 секунд до 20 мс, просто изменив тип данных. Я даже дошел до того, что преобразовал мой вызов linq в sql в простой старый запрос sql и использовал метод .ExecuteQuery () контекста данных для его запуска, и он работает молниеносно. Это определенно проблема преобразования типа данных, из-за которой SQL игнорирует индексы в таблице.   -  person Jason    schedule 05.11.2009


Ответы (1)


Вы можете получить команду и напрямую сбросить типы параметров (в вашем случае на ansi-строку).

http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.getcommand.aspx http://msdn.microsoft.com/en-us/library/system.data.dbtype.aspx

Затем вы можете вызвать ExecuteReader для этой команды, получив в результате DbDataReader. Вы можете передать этот DbDataReader методу Translate вашего контекста данных, и он даст вам IEnumerable<T>, который вы ожидаете от linq.

http://msdn.microsoft.com/en-us/library/bb534213.aspx


Проблема с производительностью вызвана тем, что параметр запроса имеет другой тип, чем индекс, выбранный оптимизатором запросов. Далее происходит преобразование всего индекса в тип параметра. Это выполняется каждый раз при отправке запроса - преобразование не откладывается для последующих запросов.

Обычно я наблюдаю такое поведение при отправке набора строк в базу данных:

  //this query will get correct parameter type
db.Customers.Where(c => c.Name == "Bob")
  //this query can get incorrect parameter type
List<string> names = new List<string>(){"Amy", "Bob"};
db.Customers.Where(c => names.Contains(c.Name));
person Amy B    schedule 11.11.2009