Tôi đã cố gắng để có được đầu của tôi xung quanh này cho một vài ngày và có rất nhiều hướng dẫn xung quanh đơn vị công việc và xung quanh TransactionScope nhưng tôi không thể tìm thấy bất cứ điều gì mà nói về cả hai cùng nhau. Bất kỳ giúp đỡ nhiều đánh giá cao!Đơn vị công việc mẫu với các giao dịch cơ sở dữ liệu
Tôi đang sử dụng Khung thực thể với mẫu Đơn vị công việc và một kho lưu trữ cho mỗi loại. Theo mã đơn giản dưới đây tôi có một thực thể Member và MembershipDefinition. Tôi muốn tạo một thực thể thành viên liên kết hai nhưng khi tôi tạo đối tượng thành viên, tôi muốn truy vấn DB cho một giá trị tối đa dựa trên một số logic nghiệp vụ. Vì vậy, tôi cần phải sử dụng một số loại giao dịch DB để ngăn chặn một thread khác tăng giá trị trong db trước khi thread của tôi đã viết đối tượng Membership trở lại DB.
Nếu tôi đã sử dụng được lưu trữ procs, đây sẽ là khá đơn giản nhưng tôi không thể tìm ra cách để làm điều đó bằng tinh khiết C# ...
Đoạn code dưới đây tạo ra 100 đơn vị thành viên trong cơ sở dữ liệu với MembershipNumbers trùng lặp . Tôi cần sử dụng giao dịch này để đảm bảo rằng tất cả các số thành viên được tạo trong mã C# là duy nhất.
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; }
}
bạn có chắc chắn giao dịch là đủ? –
Bạn có thể gọi Thủ tục lưu trữ qua Entity Framework, vì vậy tại sao làm phức tạp công việc bạn phải – podiluska
Tôi thấy câu hỏi là một câu hỏi tổng quát hơn: làm thế nào để giảm độ phức tạp của hệ thống theo cách mà chúng ta có thể giải thích về tính chính xác của hệ thống . Trong trường hợp này, chúng tôi có thể giải quyết vấn đề cho MAX(), nhưng làm thế nào chúng ta có thể chắc chắn rằng hệ thống hoạt động dự kiến, không bế tắc, và không chạy chậm. Ngay cả với một giao dịch serializable, bạn không thể chắc chắn rằng hệ thống của bạn hoạt động tốt khi chạy các hoạt động song song. – Steven