2017-02-06 9 views
0

Я создаю приложение ASP.NET MVC 5, чтобы получить доступ только для чтения от 2 до 12 строк в время. Записи хранятся в Oracle 11 и доступны через Entity Framework 6 из представления в Oracle. Как говорит название, это быстро с жестко заданным значением, но медленно с параметром строки (пример ниже) Это работает быстро:Извлечение записей из представления Oracle (в Entity Framework) выполняется быстро с жестко закодированным строковым значением, но медленным с параметром строки

public List<VW_COLLISIONS_TS> GetCollisions(string collisionMRN) 
{ 
     var collisions = (from c in TSP_Context.VW_COLLISIONS_TS 
      where c.COLLISION_MASTER_RECORD_NUMBER.Equals("902770479") 
          select c).AsNoTracking(); 

     return collisions.ToList(); 
} 

Но это работает медленно:

public List<VW_COLLISIONS_TS> GetCollisions(string collisionMRN) 
{ 
     var collisions = (from c in TSP_Context.VW_COLLISIONS_TS 
      where .COLLISION_MASTER_RECORD_NUMBER.Equals(collisionMRN) 
          select c).AsNoTracking(); 


     return collisions.ToList(); 
} 

It занимает примерно 30 секунд с параметром для возврата записей. Почему это?

UPDATE: Я создал след, это то, что я получил:

[#1 - with hard-coded string value] 
Opened connection at 2/9/2017 9:48:29 AM -05:00 
SELECT 
"Extent1"."PERSON_MASTER_RECORD_NUMBER" AS "PERSON_MASTER_RECORD_NUMBER", 
"Extent1"."VEHICLE_MODEL" AS "VEHICLE_MODEL", 
"Extent1"."PERSON_AGE" AS "PERSON_AGE" 
FROM "DWOBDEV"."VW_COLLISIONS_TS" "Extent1" 
WHERE ('902770479' = "Extent1"."COLLISION_MASTER_RECORD_NUMBER") 
-- Executing at 2/9/2017 9:48:29 AM -05:00 
-- Completed in 5 ms with result: OracleDataReader 
Closed connection at 2/9/2017 9:44:29 AM -05:00 

[2. With string parameter] 
Opened connection at 2/9/2017 9:44:17 AM -05:00 
SELECT 
"Extent1"."PERSON_MASTER_RECORD_NUMBER" AS "PERSON_MASTER_RECORD_NUMBER", 
"Extent1"."VEHICLE_MODEL" AS "VEHICLE_MODEL", 
"Extent1"."PERSON_AGE" AS "PERSON_AGE" 
FROM "DWOBDEV"."VW_COLLISIONS_TS" "Extent1" 
WHERE (("Extent1"."COLLISION_MASTER_RECORD_NUMBER" = :p__linq__0) OR (("Extent1"."COLLISION_MASTER_RECORD_NUMBER" IS NULL) AND (:p__linq__0 IS NULL))) 
-- p__linq__0: '902770479' (Type = Object) 
-- Executing at 2/9/2017 9:44:17 AM -05:00 
-- Completed in 12364 ms with result: OracleDataReader 
Closed connection at 2/9/2017 9:48:29 AM -05:00 
взять

моего сослуживца: «Я думаю, когда вы жестко закодировать его обработки, как число/целое число и при использовании string обрабатывается как varchar/text, а затем ищет нули. Попробуйте использовать COLLISION_MASTER_RECORD_NUMBER как целочисленную переменную, если COLLISION_MASTER_RECORD_NUMBER имеет тип данных номер/тип. "

Что вы, ребята, думаете? [Примечание: В настоящее время COLLISION_MASTER_RECORD_NUMBER является varchar2 'число' (без альфа-канала) в базе данных Oracle]

UPDATE (Ответил!): Из того, что Александр V писал (включая ссылку EF), я придумал с этим:

var collisions = (from c in TSP_Context.VW_COLLISIONS_TS 
          where c.COLLISION_MASTER_RECORD_NUMBER == (DbFunctions.AsNonUnicode(collisionMRN)) 
          select c).AsNoTracking(); 

И я добавил это в конструкторе Context:

this.Configuration.UseDatabaseNullSemantics = true; 

это работало хорошо.

ответ

0

Вам нужно проверить, какой SQL-запрос генерируется в обоих случаях.

Попробуйте добавить это перед .ToList() вызов:

var sql = ((System.Data.Entity.Core.Objects.ObjectQuery)collisions) 
      .ToTraceString(); 

Если бы вы могли опубликовать SQL запросов назад, мы увидим, что здесь происходит.

UPDATE: (на основе обновления запросов SQL, который разместил @R Jo.)

Я думаю, что проблема с производительностью в 2-ом запросе связана с дополнительными проверками NULL: поэтому попробуйте использовать == "something" вместо .Equals("something") потому что Equals могут генерировать дополнительные проверки null для типов с нулевым значением; , и мы EF должны работать с двумя разными типами данных здесь, когда вы делаете Equals, и мы тоже хотим этого избежать. (см. пример ниже). Если код примера не работает, попробуйте это ' UseDatabaseNullSemantics = true; может помочь. (см. Здесь Why is EF generating SQL queries with unnecessary null-checks?.

EDIT:

если COLLISION_MASTER_RECORD_NUMBER тогда мы могли бы сделать что-то вроде

public List<VW_COLLISIONS_TS> GetCollisions(string collisionMRN) 
{ 
     int collision = int.Parse(collisionMRN); 
     var collisions = (from c in TSP_Context.VW_COLLISIONS_TS 
      where .COLLISION_MASTER_RECORD_NUMBER == collision 
          select c).AsNoTracking(); 


     return collisions.ToList(); 
} 

Пожалуйста, дайте мне знать, если это будет работать для вас.

+0

Спасибо! Я попробую. –

+0

Я сказал Oracle 11, это на самом деле в Oracle 12. –

+0

@ R.Jo Наряду с созданным SQL, пожалуйста, получите план выполнения. – BobC

 Смежные вопросы

  • Нет связанных вопросов^_^