0

Does the TransactionScope object also synchronizes the access to code among Multiple threads of Users ? OR, it only declares the code (Business Operations) as atomic (single Transaction)?

Details: 1. I am implementing UnitOfWork class for Repositories in Infrastructure Layer which itself is defined as class library project (dll).

  1. Repository contains reference to object of UnitOfWork to call its methods which maintain diciontary/collection of Entities that has been added, changed Or updated.

  2. Unit of Work class has a member function Commits() which has the code wrapped inside TransactionScope object.

Consider that Multiple users access the Domain/Business objects then i presume that each user will have its own set of business objects running in its thread.

I am not sure what TransactionScope object will do in this case ? Is it just decalring the multiple operations inside a user thread as single business transaction ? OR it is synchronizing the acess to code also among different threads of user/s? The code of UnitOfWork class is as below:

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
}
4

2 回答 2

0
  1. 我的问题也在示例标题 P11 下的此链接中得到解答:http: //www.codeproject.com/Articles/18743/Interfaces-in-C-For-Beginners

  2. 问这个问题的原因只是为了确认接口上的面向对象规则,该规则在讨论领域驱动设计书时陈述,其中 Repositoary Factory 类返回 IRepository 的通用类型,这也意味着 RepositoryFactory 将能够返回 IRepository 或除了实现它之外,任何扩展 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 < TEntity > 接口,并且 TEntity 派生自 EntityBase 类。因为 Repository Framework 支持的接口不只是 IRepository < T > ,所以该方法不能只返回 Repository 实例的 IRepository < T > 类型。它还必须支持返回任何实现 IRepository < T > 的接口,因为正在使用的存储库接口也可以在其中定义其他方法;这就是为什么 TRepository 被声明为通用类型的原因,

---讨论到此结束---

于 2013-09-10T06:58:24.800 回答
0

@Adil Mughal:非常感谢,您的及时回答真的很有帮助。有关 C#.NET 上下文中术语“线程安全”的更多详细信息,我还获得了一些有用的链接,并希望在下面分享:(由此我得到的是 TransactionScope 对象是“线程安全的”,这意味着TransactionScope 对象块中的任何代码都由 .NET 很好地同步,并且访问代码块的多个线程不会产生并发问题,例如它会锁定代码块)

“线程安全”的真正含义是什么......在实际中

是什么使方法线程安全?都有些什么样的规矩?

.NET 中的线程安全集合

http://www.codeproject.com/Articles/37976/Writing-Thread-Safe-Code-in-C

http://www.albahari.com/threading/part2.aspx

问候, 法哈尔·安瓦尔

于 2013-09-10T07:21:57.957 回答