Cancelling an Entity Framework Query

前端 未结 1 2034
野趣味
野趣味 2020-12-08 07:30

I\'m in the process of writing a query manager for a WinForms application that, among other things, needs to be able to deliver real-time search results to the user as they\

相关标签:
1条回答
  • 2020-12-08 08:29

    Looks like you have found some bug in EF but when you report it to MS it will be considered as bug in documentation. Anyway I don't like the idea of interacting directly with EntityCommand. Here is my example how to kill current query:

    var thread = new Thread((param) =>
        {
            var currentString = param as string;
    
            if (currentString == null)
            {
                // TODO OMG exception
                throw new Exception();
            }
    
            AdventureWorks2008R2Entities entities = null;
            try // Don't use using because it can cause race condition
            {
                entities = new AdventureWorks2008R2Entities();
    
                ObjectQuery<Person> query = entities.People
                    .Include("Password")
                    .Include("PersonPhone")
                    .Include("EmailAddress")
                    .Include("BusinessEntity")
                    .Include("BusinessEntityContact");
                // Improves performance of readonly query where
                // objects do not have to be tracked by context
                // Edit: But it doesn't work for this query because of includes
                // query.MergeOption = MergeOption.NoTracking;
    
                foreach (var record in query 
                    .Where(p => p.LastName.StartsWith(currentString)))
                {
                    // TODO fill some buffer and invoke UI update
                }
            }
            finally
            {
                if (entities != null)
                {
                    entities.Dispose();
                }
            }
        });
    
    thread.Start("P");
    // Just for test
    Thread.Sleep(500);
    thread.Abort();
    

    It is result of my playing with if after 30 minutes so it is probably not something which should be considered as final solution. I'm posting it to at least get some feedback with possible problems caused by this solution. Main points are:

    • Context is handled inside the thread
    • Result is not tracked by context
    • If you kill the thread query is terminated and context is disposed (connection released)
    • If you kill the thread before you start a new thread you should use still one connection.

    I checked that query is started and terminated in SQL profiler.

    Edit:

    Btw. another approach to simply stop current query is inside enumeration:

    public IEnumerable<T> ExecuteQuery<T>(IQueryable<T> query)
    {
        foreach (T record in query)
        {
            // Handle stop condition somehow
            if (ShouldStop())
            {
                // Once you close enumerator, query is terminated
                yield break;
            }
            yield return record;
        }
    }
    
    0 讨论(0)
提交回复
热议问题