知识大全 EntityFramework用法探索:线程安全实践
Posted 知
篇首语:捐躯赴国难,视死忽如归。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 EntityFramework用法探索:线程安全实践相关的知识,希望对你有一定的参考价值。
EntityFramework用法探索:线程安全实践 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
在前文中 我们通过Unity来注册各种类型和WiringUp
IUnityContainer container = new UnityContainer()
RegisterType(typeof(IRepository<>) typeof(Repository<>) new ContainerControlledLifetimeManager())
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
UnityServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator SetLocatorProvider(() => locator);
ICustomerRepository customerRepository = container Resolve
但选择使用了ContainerControlledLifetimeManager对象生命周期管理器 其将每个对象存储为Singleton 这导致在多线程环境下会产生异常
例如我们尝试在多线程条件下更新Customer表
List
for (int i = ; i < ; i++)
DomainModels Customer modifiedCustomer = Mapper Map
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
= 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
= 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
RegisterType
RegisterType
RegisterType
RegisterType
RegisterType
UnityContainerDispatcher InjectParentContainer(container);
ICustomerRepository customerRepository = container Resolve
创建多线程测试代码
List
for (int i = ; i < ; i++)
DomainModels Customer modifiedCustomer = Mapper Map
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相关参考