C#.NET: синхронизирует ли объект TransactionScope доступ к коду между несколькими потоками пользователей?
Является ли объект TransactionScope также синхронизирует доступ к коду среди нескольких потоков пользователей? ИЛИ он только объявляет код (бизнес-операции) как атомарный (одна транзакция)?
Подробности: 1. Я реализую класс UnitOfWork для репозиториев на уровне инфраструктуры, который сам по себе определен как проект библиотеки классов (dll).
Репозиторий содержит ссылку на объект UnitOfWork для вызова его методов, которые поддерживают словарь / коллекцию сущностей, которые были добавлены, изменены или обновлены.
Класс Unit of Work имеет функцию-член Commits(), код которой заключен в объект TransactionScope.
Учтите, что несколько пользователей получают доступ к объектам домена / бизнеса, тогда я предполагаю, что у каждого пользователя будет свой собственный набор бизнес-объектов, работающих в его потоке.
Я не уверен, что объект TransactionScope будет делать в этом случае? Это просто удаление нескольких операций внутри пользовательского потока как одной бизнес-транзакции? ИЛИ это синхронизирует доступ к коду также среди разных потоков пользователя / ов? Код класса 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
}
2 ответа
На мой вопрос также ответили по этой ссылке под заголовком примера P11: http://www.codeproject.com/Articles/18743/Interfaces-in-C-For-Beginners
Причиной для того, чтобы задать этот вопрос, было просто подтвердить объектно-ориентированное правило на интерфейсе, которое было заявлено во время обсуждения книги по управляемому доменом проекту, в которой класс 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
--- Обсуждение ENDS здесь ---
@ Адиль Могал: Большое спасибо, ваш быстрый ответ действительно помогает. Для получения дополнительной информации о том, что является термином "потокобезопасный" в контексте 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
С уважением, Фахар Анвар