2016-06-23 2 views
2

Предполагая, что у меня есть:два различных запросов LINQ против того же Entity Framework DbSet, возвращают те же результаты

class ContractContext : DbContext 
{ 
    DbSet<ACTIVITY> ACTIVITYs { get; set; } 
} 

И у меня есть следующий код, где startSnapshot и endSnapshot целые числа со значениями 1 и 2:

var activitiesStart = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == startSnapshot); 
var activitiesEnd = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == endSnapshot); 

Эти два запроса возвратят тот же результат. Этот результат будет результатом первого из этих двух выполняемых запросов. Так что, если я заставляю их обоих, чтобы выполнить с ToList(),

var activitiesStart = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == startSnapshot).ToList(); 
var activitiesEnd = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == endSnapshot).ToList(); 

Тогда результат сохраняется в activitiesEnd будет результат выполнения запроса activitiesStart. Если я сначала выполнил запрос activityEnd, тогда будет обратное. Что происходит? Я понимаю, что они являются одним и тем же контекстом, и я думаю, я могу видеть, как это может быть может объединить запросы, если я создам их как до того, как либо выполняется. Во втором случае, однако, один выполняется до того, как другой был даже создан, так почему он попирает второй запрос?

Сгенерированный SQL (одинакова для обоих):

{SELECT 
    [Extent1].[ACTIVITY_ID] AS [ACTIVITY_ID], 
    [Extent1].[ACTIVITY_NAME] AS [ACTIVITY_NAME], 
    [Extent1].[WBS_ID] AS [WBS_ID], 
    [Extent1].[VARIANCE_SNAPSHOT_ID] AS [VARIANCE_SNAPSHOT_ID], 
    [Extent1].[DUE_DATE] AS [DUE_DATE], 
    [Extent1].[IS_COMPLETE] AS [IS_COMPLETE] 
FROM [p6].[ACTIVITY] AS [Extent1] 
WHERE [Extent1].[VARIANCE_SNAPSHOT_ID] = @p__linq__0} 

Пример

var activitiesStart = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == 1).ToList(); 
var activitiesEnd = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == 2).ToList(); 

foreach (var item in activitiesStart) 
{ 
    Debug.Write(item.VARIANCE_SNAPSHOT_ID + " "); 
} 

Debug.WriteLine(""); 

foreach (var item in activitiesEnd) 
{ 
    Debug.Write(item.VARIANCE_SNAPSHOT_ID + " "); 
} 

Debug.WriteLine(""); 

Это выводит два ряда из них, потому что activitiesStart была выполнена в первую очередь. Если я поменяю их, я получаю две строки по два. Профилировщик SQL Server показывает, что запросы были правильно отправлены на сервер.

+0

Каковы значения startSnapshot и endSnapshot? Как назначаются люди? –

+0

Я не вижу причин, по которым они будут влиять друг на друга. Когда вы отлаживаете до первого оператора, каковы значения startSnapshot и endSnapShot? – sovemp

+0

Они являются параметрами функции, а в моем тестовом случае - 1 (начало) и 2 (конец). Я уточню вопрос. –

ответ

0

Я не смог понять это. Моим решением было использовать AsNoTracking на первом выполненном.

var activitiesStart = contractContext.ACTIVITYs.AsNoTracking.Where(a => a.VARIANCE_SNAPSHOT_ID == startSnapshot).ToList(); 
var activitiesEnd = contractContext.ACTIVITYs.Where(a => a.VARIANCE_SNAPSHOT_ID == endSnapshot).ToList(); 
+0

Тем не менее, это показывает, что в вашей модели что-то не так. Я никогда не видел ничего подобного. Я бы не согласился на обход. Если вы не дойдете до конца, рано или поздно это вызовет у вас больше проблем. –

0

Возможно получить некоторые перекрестные помехи между запросами из-за того, как работает отложенное выполнение. Запросы будут выполняться против значения параметра во время выполнения (т. Е. Когда это ToList() или потребляется в противном случае).

  var idA = 614; 
      var idB = 130; 

      var context = DbModel.ContextManager.Prism.dbo(DBName_Static); 
      var custA = context.Customer.Where(x => x.Id == idA); 
      var custB = context.Customer.Where(x => x.Id == idB); 

      //different results (correct) 
      var custA_forcedBefore = custA.ToList(); 
      var custB_forcedBefore = custB.ToList(); 

      //change the value of the input params to be the same 
      idA = idB; 

      //same results (incorrect). Because execution was deferred til after the parameter values were changed 
      var custA_forcedAfter = custA.ToList(); 
      var custB_forcedAfter = custB.ToList(); 

Редактировать: Следует отметить, что когда я столкнулся с этой проблемой, это было не все в одной и той же функции. Значение входных параметров было изменено в сторону стека после того, как я ошибочно предположил, что запросы уже выполнены.

+0

Это имеет полное значение для меня - я бы предположил, что EF связывает ссылку с параметром, а не значением параметра. Однако, если вы посмотрите на третий блок кода в моем сообщении, вы увидите, что я выполняю запросы с разными переменными. Никогда не бывает времени, когда я устанавливаю его равным другому. Также см. Раздел «Пример», где я жестко закодировал значения, и я получаю ту же проблему. –

+0

@TomSchultz Учитывая, что вы сделали немедленный ToList() и подтвердили значения параметров в sql-профилировщике, я бы с удовольствием согласился с тем, что это не значение значения параметра отложенного исполнения. Это могучий странный ... – Derpy

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