They tried to get around this for a couple of days, and there are a lot of tutorials around the unit of work and around TransactionScope, but I can not find anything that says about them together. Any help is much appreciated!
I am using Entity Framework with Unit Of Work template and repository for each type. According to the simple code below, I have a Member member and MembershipDefinition. I want to create a Membership object that links two, but when I create a Membership object. I want to query DB for maximum value based on some business logic . Therefore, I need to use some kind of database transaction to prevent another thread from adding a value to db before my thread writes the Membership object back to the database.
If I used stored procs, that would be pretty simple, but I can't figure out how to do this using pure C # ...
The code below creates 100 database memberships with duplicate MembershipNumbers. I need to use this use to use transactions to ensure that all membership numbers generated in C # code are unique.
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 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; } }
Matt austin
source share