TransactionScope对象是否还同步多个用户线程之间的代码访问?或者,它只将代码(业务操作)声明为原子(单个事务)?
详细说明: 1.我正在为Infrastructure Layer中的Repositories实现UnitOfWork类,它本身被定义为类库项目(dll)。
Repository包含对UnitOfWork对象的引用,以调用其方法,该方法维护已添加,更改或更新的实体的diciontary /集合。
Unit of Work类有一个成员函数Commits(),其代码包含在TransactionScope对象中。
考虑到多个用户访问域/业务对象,然后我假设每个用户将在其线程中运行自己的一组业务对象。
我不确定在这种情况下TransactionScope对象会做什么?它只是将用户线程内的多个操作判断为单个业务事务吗?或者它也在用户/ s的不同线程之间同步访问代码? UnitOfWork类的代码如下:
public class UnitOfWork
{
private Dictionary<EntityBase, IUnitOfWorkRepository> addedEntities;
private Dictionary<EntityBase, IUnitOfWorkRepository> changedEntities;
private Dictionary<EntityBase, IUnitOfWorkRepository> deletedEntities;
public UnitOfWork()
{
this.addedEntities = new Dictionary<EntityBase, IUnitOfWorkRepository>();
this.changedEntities = new Dictionary<EntityBase, IUnitOfWorkRepository>();
this.deletedEntities = new Dictionary<EntityBase, IUnitOfWorkRepository>();
}
#region IUnitOfWork Members
public void RegisterAdded(EntityBase entity, IUnitOfWorkRepository repository)
{
this.addedEntities.Add(entity, repository);
}
public void RegisterChanged(EntityBase entity, IUnitOfWorkRepository repository)
{
this.changedEntities.Add(entity, repository);
}
public void RegisterRemoved(EntityBase entity, IUnitOfWorkRepository repository)
{
this.deletedEntities.Add(entity, repository);
}
public void Commit()
{
using (TransactionScope scope = new TransactionScope())
{
foreach (EntityBase entity in this.deletedEntities.Keys)
{
this.deletedEntities[entity].PersistDeletedItem(entity);
}
foreach (EntityBase entity in this.addedEntities.Keys)
{
this.addedEntities[entity].PersistDeletedItem(entity);
}
foreach (EntityBase entity in this.changedEntities.Keys)
{
this.changedEntities[entity].PersistDeletedItem(entity);
}
scope.Complete();
}
this.deletedEntities.Clear();
this.addedEntities.Clear();
this.changedEntities.Clear();
}
#endregion
}
答案 0 :(得分:0)
我的问题在示例标题P11下的此链接中得到了回答:http://www.codeproject.com/Articles/18743/Interfaces-in-C-For-Beginners
提出这个问题的原因只是为了确认在关于域驱动设计的讨论中陈述的界面上的面向对象规则,其中Repositoary Factory类返回一个通用类型的IRepository,这也意味着RepositoryFactory将会除了实现它之外,能够返回IRepository OR任何接口或类扩展IRepository(这就是我认为.NET泛型的解释方式(完整代码和讨论如下)。
---讨论在这里开始---
- 代码
using System;
using System.Collections.Generic;
using SmartCA.Infrastructure;
using SmartCA.Infrastructure.DomainBase;
using SmartCA.Infrastructure.RepositoryFramework.Configuration;
using System.Configuration;
namespace SmartCA.Infrastructure.RepositoryFramework
{
public static class RepositoryFactory
{
// Dictionary to enforce the singleton pattern
private static Dictionary < string, object > repositories = new
Dictionary < string, object > ();
/// < summary >
/// Gets or creates an instance of the requested interface. Once a
/// repository is created and initialized, it is cached, and all
/// future requests for the repository will come from the cache.
/// < /summary >
/// < typeparam name=”TRepository” > The interface of the repository
/// to create. < /typeparam >
/// < typeparam name=”TEntity” > The type of the EntityBase that the
/// repository is for. < /typeparam >
/// < returns > An instance of the interface requested. < /returns >
public static TRepository GetRepository < TRepository, TEntity > ()
where TRepository : class, IRepository < TEntity >
where TEntity : EntityBase
{
// Initialize the provider’s default value
TRepository repository = default(TRepository);
string interfaceShortName = typeof(TRepository).Name;
// See if the provider was already created and is in the cache
if (!RepositoryFactory.repositories.ContainsKey(interfaceShortName))
{
// Not there, so create it
// Get the repositoryMappingsConfiguration config section
RepositorySettings settings =
(RepositorySettings)ConfigurationManager.GetSection(RepositoryMappingConstants
.RepositoryMappingsConfigurationSectionName);
// Create the repository, and cast it to the interface specified
repository =
Activator.CreateInstance(Type.GetType(settings.RepositoryMappings[interfaceShortName]
.RepositoryFullTypeName)) as TRepository;
// Add the new provider instance to the cache
RepositoryFactory.repositories.Add(interfaceShortName, repository);
}
else
{
// The provider was in the cache, so retrieve it
repository =
(TRepository)RepositoryFactory.repositories[interfaceShortName];
}
return repository;
}
}
}
- 代码
这种方法的签名很有意思,因为它使用了两个通用类型参数,即TRepository和TEntity,其限制是TRepository是一个类并实现了IRepository&lt; TEntity&gt;接口,TEntity派生自EntityBase类。因为Repository Framework支持除IRepository之外的接口&lt; T> ,该方法不能只返回一种类型的IRepository&lt; T>对于Repository实例。它还必须支持返回任何实现IRepository的接口&lt; T> ,因为正在使用的存储库接口也可以在其中定义其他方法;这就是为什么TRepository被声明为通用类型,以便工厂可以支持 Repository Framework要求能够传递有效的Repository接口类型并获取接口的实例(只要它已在应用程序的配置文件中正确定义)。
---讨论结束这里---
答案 1 :(得分:0)
@Adil Mughal:非常感谢,你的快速回答确实有帮助。有关C#.NET上下文中“线程安全”一词的更多详细信息,我还得到了一些有用的链接,并希望在下面分享:(从我得到的是,TransactionScope对象是“线程安全的”,这意味着TransactionScope对象块中的任何代码都由.NET很好地同步,并且访问代码块的多个线程不会产生并发问题,比如它会锁定代码块。
What "thread safe" really means...In Practical terms
What Makes a Method Thread-safe? What are the rules?
Thread safe collections in .NET
http://www.codeproject.com/Articles/37976/Writing-Thread-Safe-Code-in-C
http://www.albahari.com/threading/part2.aspx
此致 Fakhar Anwar