Шаблон единицы работы с транзакциями базы данных

Я пытался понять это в течение нескольких дней, и есть много руководств по единице работы и по TransactionScope, но я не могу найти ничего, что говорит об этих двух вместе. Любая помощь высоко ценится!

Я использую Entity Framework с шаблоном Unit Of Work и репозиторием для каждого типа. В соответствии с простым кодом ниже у меня есть сущность Member и MembershipDefinition. Я хочу создать сущность Membership, которая связывает их, но когда я создаю объект Membership, я хочу запросить у БД максимальное значение на основе некоторой бизнес-логики . Поэтому мне нужно использовать какую-то транзакцию БД, чтобы предотвратить увеличение значения в БД другим потоком до того, как мой поток запишет объект членства обратно в БД.

Если бы я использовал хранимые процедуры, это было бы довольно просто, но я не могу понять, как это сделать, используя чистый c #...

. Приведенный ниже код создает 100 сущностей Membership в базе данных с дублированными MembershipNumbers. Мне нужно получить это использование для использования транзакций, чтобы гарантировать, что все номера участников, сгенерированные в коде c #, уникальны.

class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        p.Go();;
    }

    public void Go()
    {
        long memberId;
        long membershipDefId;

        using(var unitOfWork = new UnitOfWork())
        {
            // Setup - create test club and member entities

            var testUsername = ("TestUserName" + Guid.NewGuid()).Substring(0, 29);
            var member = new Member()
                             {
                                 UserName = testUsername
                             };

            var testmemebrshpDefName = ("TestMembershipDef" + Guid.NewGuid()).Substring(0, 29);
            var membershipDefinition = new ClubMembershipDefinition()
            {
                ClubId = 1,
                Name = testmemebrshpDefName
            };

            unitOfWork.MemberRepository.Add(member);
            unitOfWork.MembershipDefinitionRepository.Add(membershipDefinition);

            unitOfWork.Save();

            memberId = member.Id;
            membershipDefId = membershipDefinition.Id;
        }

        Task[] tasks = new Task[100];

        // Now try to add a membership to the Member object, linking it to the test Club's single Club Definition
        for (int i = 0; i < 100; i++)
        {
            var task = new Task(() => CreateMembership(memberId, membershipDefId));
            tasks[i] = task;
            task.Start();
        }
        Task.WaitAll(tasks);
    }

    private void CreateMembership(long memberId, long membershipDefId)
    {
        using (var unitOfWork = new UnitOfWork())
        {
            var member = unitOfWork.MemberRepository.GetById(memberId);
            var membershipDef = unitOfWork.MembershipDefinitionRepository.GetById(membershipDefId);

            var membership = new ClubMembership()
                                    {
                                        ClubMembershipDefinition = membershipDef
                                    };

            membership.MembershipNumber = (unitOfWork.MembershipRepository.GetMaxMembershipNumberForClub(membershipDef.ClubId) ?? 0) + 1;

            member.ClubMemberships.Add(membership);
            unitOfWork.Save();
        }
    }

}

public class UnitOfWork : IUnitOfWork, IDisposable
{
    internal ClubSpotEntities _dbContext = new ClubSpotEntities();
    internal MemberRepository _memberRepository;
    internal MembershipRepository _membershipRepository;
    internal MembershipDefinitionRepository _membershiDefinitionpRepository;

    public MemberRepository MemberRepository
    {
        get
        {
            if (_memberRepository == null)
                _memberRepository = new MemberRepository(_dbContext);

            return _memberRepository; ;
        }
    }

    public MembershipRepository MembershipRepository
    {
        get
        {
            if (_membershipRepository == null)
                _membershipRepository = new MembershipRepository(_dbContext);

            return _membershipRepository; ;
        }
    }

    public MembershipDefinitionRepository MembershipDefinitionRepository
    {
        get
        {
            if (_membershiDefinitionpRepository == null)
                _membershiDefinitionpRepository = new MembershipDefinitionRepository(_dbContext);

            return _membershiDefinitionpRepository; ;
        }
    }

    public virtual int Save()
    {
        return _dbContext.SaveChanges();

    }

    private bool _disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this._disposed)
        {
            if (disposing)
            {
                _dbContext.Dispose();
            }
        }
        this._disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

public class MembershipRepository
{
    ClubSpotEntities _dbContext = new ClubSpotEntities();

    public MembershipRepository(){}

    public MembershipRepository(ClubSpotEntities dbContext)
    {
        _dbContext = dbContext;
    }

    public IEnumerable<ClubMembership> GetAll()
    {
        return _dbContext.Set<ClubMembership>().ToList<ClubMembership>();
    }

    public ClubMembership GetById(long id)
    {
        return _dbContext.ClubMemberships.First(x => x.Id == id);
    }

    public long? GetMaxMembershipNumberForClub(long clubId)
    {
        return _dbContext.ClubMemberships.Where(x => x.ClubMembershipDefinition.ClubId == clubId).Max(x => x.MembershipNumber);
    }

    public ClubMembership Add(ClubMembership entity)
    {
        return _dbContext.Set<ClubMembership>().Add(entity);
    }

    public void Delete(ClubMembership membership)
    {
        _dbContext.Set<ClubMembership>().Remove(membership);
    }

    public void Save()
    {
        _dbContext.SaveChanges();
    }
}


public partial class ClubMembership
{
    public long Id { get; set; }
    public long MembershipDefId { get; set; }
    public Nullable<long> MemberId { get; set; }
    public Nullable<long> MembershipNumber { get; set; }

    public virtual ClubMembershipDefinition ClubMembershipDefinition { get; set; }
    public virtual Member Member { get; set; }
}

public partial class ClubMembershipDefinition
{
    public ClubMembershipDefinition()
    {
        this.ClubMemberships = new HashSet<ClubMembership>();
    }

    public long Id { get; set; }
    public long ClubId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<ClubMembership> ClubMemberships { get; set; }
}

public partial class Member
{
    public Member()
    {
        this.ClubMemberships = new HashSet<ClubMembership>();
    }

    public long Id { get; set; }
    public string UserName { get; set; }

    public virtual ICollection<ClubMembership> ClubMemberships { get; set; }
}
7
задан Matt Austin 16 August 2012 в 07:52
поделиться