知识大全 EntityFramework用法探索:线程安全实践

Posted

篇首语:捐躯赴国难,视死忽如归。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 EntityFramework用法探索:线程安全实践相关的知识,希望对你有一定的参考价值。

EntityFramework用法探索:线程安全实践  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  在前文中 我们通过Unity来注册各种类型和WiringUp

   IUnityContainer container = new UnityContainer()

   RegisterType(typeof(IRepository<>) typeof(Repository<>) new ContainerControlledLifetimeManager())

   RegisterType (new ContainerControlledLifetimeManager())

   RegisterType (new ContainerControlledLifetimeManager())

   RegisterType (new ContainerControlledLifetimeManager())

   RegisterType (new ContainerControlledLifetimeManager())

   RegisterType (new ContainerControlledLifetimeManager())

   RegisterType (new ContainerControlledLifetimeManager());

  

   UnityServiceLocator locator = new UnityServiceLocator(container);

   ServiceLocator SetLocatorProvider(() => locator);

  

   ICustomerRepository customerRepository = container Resolve ();

  但选择使用了ContainerControlledLifetimeManager对象生命周期管理器 其将每个对象存储为Singleton 这导致在多线程环境下会产生异常

  例如我们尝试在多线程条件下更新Customer表

   List tasks = new List ();

   for (int i = ; i < ; i++)

  

   DomainModels Customer modifiedCustomer = Mapper Map (customer );

   modifiedCustomer Name = modifiedCustomer Name + i;

  

   Task t = Task Factory StartNew(() =>

  

   try

  

   customerRepository UpdateCustomer(modifiedCustomer);

  

   catch (Exception ex)

  

   Console WriteLine( Exception occurred in thread + Thread CurrentThread ManagedThreadId);

   Console WriteLine(ex Message);

  

   );

   tasks Add(t);

  

   Task WaitAll(tasks ToArray());

>

  但由于我们仍然需要EntityFramework的Local功能 即在当前线程环境下始终使用当前上下文中的对象 我们可能还无法选择其他Unity对象生命期管理模型

  此时 我们考虑一种新的方法 引入线程Scope功能 即在给定线程中 使用同一个UnityContainer来维护对象 这样间接利用的EntityFramework的上下文功能

  原理很简单 就是为每个线程生成一个单独的ChildUnityContainer

   public class UnityContainerScope : IDisposable

  

   private static ConcurrentDictionary scopeMapping

   = new ConcurrentDictionary ();

  

   protected UnityContainerScope()

  

   ScopeId = Thread CurrentThread ManagedThreadId;

   scopeMapping Add(ScopeId true);

  

  

   public int ScopeId get; private set;

   public static int ScopeCount get return scopeMapping Count;

  

   public static UnityContainerScope NewScope()

  

   return new UnityContainerScope();

  

  

   public static bool InScope(int scopeId)

  

   return scopeMapping ContainsKey(scopeId);

  

  

   public void Dispose()

  

   UnityContainerDispatcher DisposeContainer();

   scopeMapping Remove(ScopeId);

  

  

  这里同时需要一个UnityContainerDispatcher来负责为线程生成Container容器

   public static class UnityContainerDispatcher

  

   private static IUnityContainer parentContainer = null;

   private static ConcurrentDictionary containerMapping

   = new ConcurrentDictionary ();

  

   public static void InjectParentContainer(IUnityContainer unity)

  

   if (unity == null)

   throw new ArgumentNullException( unity );

  

   parentContainer = unity;

  

  

   public static IUnityContainer GetContainer()

  

   int key = Thread CurrentThread ManagedThreadId;

  

   if (!UnityContainerScope InScope(key))

  

   throw new UnityContainerNotInScopeException(

   string Format(CultureInfo InvariantCulture

   The specified scope id [ ] is not in scope key));

  

  

   if (!containerMapping ContainsKey(key))

  

   BuildUpContainer(key);

  

  

   return containerMapping Get(key);

  

  

   public static void DisposeContainer()

  

   int key = Thread CurrentThread ManagedThreadId;

   IUnityContainer container = containerMapping Remove(key);

   if (container != null)

  

   container Dispose();

  

  

  

   private static void BuildUpContainer(int key)

  

   if (parentContainer == null)

   throw new InvalidProgramException( The parent container cannot be null );

  

   IUnityContainer childContainer = parentContainer CreateChildContainer();

   containerMapping Add(key childContainer);

  

  

  在注入的根UnityContainer中 我们通过使用CreateChildContainer方法来获取一个新的Container 同时继承所有根容器的注册配置信息 这要求使用HierarchicalLifetimeManager生命期管理器

  此时 我们的代码修改为

   IUnityContainer container = new UnityContainer()

   RegisterType(typeof(IRepository<>) typeof(Repository<>) new HierarchicalLifetimeManager())

   RegisterType (new HierarchicalLifetimeManager())

   RegisterType (new HierarchicalLifetimeManager())

   RegisterType (new HierarchicalLifetimeManager())

   RegisterType (new HierarchicalLifetimeManager())

   RegisterType (new HierarchicalLifetimeManager())

   RegisterType (new HierarchicalLifetimeManager());

  

   UnityContainerDispatcher InjectParentContainer(container);

  

   ICustomerRepository customerRepository = container Resolve ();

  创建多线程测试代码

   List tasks = new List ();

   for (int i = ; i < ; i++)

  

   DomainModels Customer modifiedCustomer = Mapper Map (customer );

   modifiedCustomer Name = modifiedCustomer Name + i;

  

   Task t = Task Factory StartNew(() =>

  

   try

  

   using (UnityContainerScope scope = UnityContainerScope NewScope())

  

   customerRepository UpdateCustomer(modifiedCustomer);

   Console WriteLine( Modified + modifiedCustomer Name + in thread + Thread CurrentThread ManagedThreadId);

  

  

   catch (Exception ex)

  

   Console WriteLine( Exception occurred in thread + Thread CurrentThread ManagedThreadId);

   Console WriteLine(ex Message);

  

   );

   tasks Add(t);

  

   Task WaitAll(tasks ToArray());

  测试结果表明已经可以安全的在多线程条件下工作了

> cha138/Article/program/net/201311/12626

相关参考