Entity Framework Transaction With Multiple Threads

China☆狼群 提交于 2019-12-04 04:15:47

The problem is described here:

http://www.b10g.dk/2007/09/07/dependenttransaction-and-multithreading/

It's easy enough to lock the SaveChanges and Refresh calls, but in order to make sure locks occur during query execution I had to make a dummy query provider that locks when executing queries. I really shouldn't have had to do this. Entity Framework should have been robust enough to handle this out of the box...especially considering you're not meant to handle your own connection creation.

Here is the code for the query provider wrapper. The IQueryables themselves and the base QueryProvider class are simple reusable implementations based off here http://blogs.msdn.com/b/mattwar/archive/2007/07/30/linq-building-an-iqueryable-provider-part-i.aspx

    /// <summary>
    /// A wrapper for queries executed by EF.
    /// </summary>
    internal class EntityFrameworkQueryProvider : QueryProvider
    {    
        protected override object Execute(Expression expression)
        {
            try
            {
                // this is required due to a bug in how EF multi-threads when Transactions are used.
                if (Transaction.Current != null) Monitor.Enter(EntityFrameworkExtensions.SyncRoot);

                // enumerate is a simple extension method that forces enumeration of the IQueryable, thus making it actually get executed during the lock
                return Expression.Lambda(expression).Compile().DynamicInvoke().Enumerate();
            }
            finally
            {
                if (Transaction.Current != null) Monitor.Exit(EntityFrameworkRepositoryProvider.SyncRoot);
            }
        }
    }

If you are passing the same instance of the dependent clone to multiple threads, and then disposing of them on each thread, that could lead to behavior like this (e.g. committing a finished transaction and such). AFAIK, you need a separate dependent clone per thread.

Another possibility is the "parent" transaction is getting completed or disposed before the threads finish with their transaction. Make sure your async work is done before you leave the main TranscationScope (although this can be set to block on unfinished child transactions).

Sorry, don't have more than that with what you've described.

Good luck, Michael

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!