简体   繁体   中英

Two different LINQ queries against the same Entity Framework DbSet, both return the same results

Assuming I have:

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

And I have the following code, where startSnapshot and endSnapshot are integers with values 1 and 2:

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

Those two queries will return the same result. That result will be the result from the first one of those two queries that executes. So if I force them both to execute with a 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();

Then the result stored in activitiesEnd will be the result from the activitiesStart query. If I execute the activitiesEnd query first then the opposite will be true. What's going on? I understand that they are the same context, and I guess I can see how it might combine the queries if I create them both before either is executed. In the second case, however, one is executed before the other is even created so why is it trampling the second query?

Generated SQL (same for both):

{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}

Example

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("");

This prints out two rows of ones, because activitiesStart was executed first. If I swap them I get two rows of twos. The SQL Server Profiler shows that the queries were properly sent to the server.

It is possible to get some crosstalk between queries due to the way deferred execution works. The queries will run against the parameter's value at the time of execution (ie when it is ToList() or consumed otherwise).

            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();

Edit: I should note that when I ran into this issue it was not all in the same function. The value of the input parameters had been changed way up the stack after I had falsely assumed the queries had already executed.

I wasn't able to figure this out. My solution was to use AsNoTracking on the first one executed.

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM