我在这里使用正确的工作单元吗? (Entityi框架4 POCO)
我找到了一些如何使用 ef4 创建工作单元的示例,我没有使用过 di/ioc,我想让事情变得简单,这是一个示例(90% 受到启发),我认为这没问题,但因为我正在查看从现在开始使用的一种模式我想最后一次征求意见。
public interface IUnitOfWork
{
void Save();
}
public partial class TemplateEntities : ObjectContext, IUnitOfWork
{
....
public void Save()
{
SaveChanges();
}
}
public interface IUserRepository
{
User GetUser(string username);
string GetUserNameByEmail(string email);
void AddUser(User userToAdd);
void UpdateUser(User userToUpdate);
void DeleteUser(User userToDelete);
//some other
}
public class UserRepository : IUserRepository, IDisposable
{
public TemplateEntities ctx;
public UserRepository(IUnitOfWork unit)
{
ctx = unit as TemplateEntities;
}
public User GetUser(string username)
{
return (from u in ctx.Users
where u.UserName == username
select u).SingleOrDefault();
}
public string GetUserNameByEmail(string email)
{
return (from u in ctx.Users
where u.Email == email
select u.UserName).SingleOrDefault();
}
public void AddUser(User userToAdd)
{
ctx.Users.AddObject(userToAdd);
}
public void UpdateUser(User userToUpdate)
{
ctx.Users.Attach(userToUpdate);
ctx.ObjectStateManager.ChangeObjectState(userToUpdate, System.Data.EntityState.Modified);
}
public void DeleteUser(User userToDelete)
{
ctx.Users.Attach(userToDelete);
ctx.ObjectStateManager.ChangeObjectState(userToDelete, System.Data.EntityState.Deleted);
}
public void Dispose()
{
if (ctx != null)
ctx.Dispose();
}
}
最后,
public class BogusMembership : MembershipProvider
{
public MembershipCreateStatus CreateUser(string username, string password, string email, bool autoemail, string fullname)
{
IUnitOfWork ctx = new TemplateEntities();
using (UserRepository rep = new UserRepository(ctx))
{
using (TransactionScope tran = new TransactionScope())
{
if (rep.GetUser(username) != null)
return MembershipCreateStatus.DuplicateUserName;
if (requiresUniqueEmail && !String.IsNullOrEmpty(rep.GetUserNameByEmail(email)))
return MembershipCreateStatus.DuplicateEmail;
User userToCreate = new User
{
UserName = username,
PassWord = EncodePassword(password),
FullName = fullname,
Email = email,
AutoEmail = autoemail
};
try
{
rep.AddUser(userToCreate);
ctx.Save();
tran.Complete();
return MembershipCreateStatus.Success;
}
catch
{
return MembershipCreateStatus.UserRejected;
}
}
}
}
}
在去掉 IUnitOfWork 和 IDisposal 后,CreateUser 看起来像这样:
public MembershipCreateStatus CreateUser(string username, string password, string email, bool autoemail, string fullname)
{
using (TransactionScope tran = new TransactionScope())
{
using (TemplateEntities ctx = new TemplateEntities())
{
UserRepository rep = new UserRepository(ctx);
//OtherRepository rep2 = new OtherRepository(ctx);
if (rep.GetUser(username) != null)
return MembershipCreateStatus.DuplicateUserName;
if (requiresUniqueEmail && !String.IsNullOrEmpty(rep.GetUserNameByEmail(email)))
return MembershipCreateStatus.DuplicateEmail;
User userToCreate = new User
{
UserName = username,
PassWord = EncodePassword(password),
FullName = fullname,
Email = email,
AutoEmail = autoemail
};
try
{
rep.AddUser(userToCreate);
ctx.SaveChanges();
tran.Complete();
return MembershipCreateStatus.Success;
}
catch
{
return MembershipCreateStatus.UserRejected;
}
}
}
}
I found some examples of how to create unit of work with ef4, i haven't used di/ioc and i would like to keep things simple and this an example (90% inspired) and i think it's ok but since i am looking at a pattern to use from now on i would like to ask an opinion one last time.
public interface IUnitOfWork
{
void Save();
}
public partial class TemplateEntities : ObjectContext, IUnitOfWork
{
....
public void Save()
{
SaveChanges();
}
}
public interface IUserRepository
{
User GetUser(string username);
string GetUserNameByEmail(string email);
void AddUser(User userToAdd);
void UpdateUser(User userToUpdate);
void DeleteUser(User userToDelete);
//some other
}
public class UserRepository : IUserRepository, IDisposable
{
public TemplateEntities ctx;
public UserRepository(IUnitOfWork unit)
{
ctx = unit as TemplateEntities;
}
public User GetUser(string username)
{
return (from u in ctx.Users
where u.UserName == username
select u).SingleOrDefault();
}
public string GetUserNameByEmail(string email)
{
return (from u in ctx.Users
where u.Email == email
select u.UserName).SingleOrDefault();
}
public void AddUser(User userToAdd)
{
ctx.Users.AddObject(userToAdd);
}
public void UpdateUser(User userToUpdate)
{
ctx.Users.Attach(userToUpdate);
ctx.ObjectStateManager.ChangeObjectState(userToUpdate, System.Data.EntityState.Modified);
}
public void DeleteUser(User userToDelete)
{
ctx.Users.Attach(userToDelete);
ctx.ObjectStateManager.ChangeObjectState(userToDelete, System.Data.EntityState.Deleted);
}
public void Dispose()
{
if (ctx != null)
ctx.Dispose();
}
}
And finally
public class BogusMembership : MembershipProvider
{
public MembershipCreateStatus CreateUser(string username, string password, string email, bool autoemail, string fullname)
{
IUnitOfWork ctx = new TemplateEntities();
using (UserRepository rep = new UserRepository(ctx))
{
using (TransactionScope tran = new TransactionScope())
{
if (rep.GetUser(username) != null)
return MembershipCreateStatus.DuplicateUserName;
if (requiresUniqueEmail && !String.IsNullOrEmpty(rep.GetUserNameByEmail(email)))
return MembershipCreateStatus.DuplicateEmail;
User userToCreate = new User
{
UserName = username,
PassWord = EncodePassword(password),
FullName = fullname,
Email = email,
AutoEmail = autoemail
};
try
{
rep.AddUser(userToCreate);
ctx.Save();
tran.Complete();
return MembershipCreateStatus.Success;
}
catch
{
return MembershipCreateStatus.UserRejected;
}
}
}
}
}
After getting rid if the IUnitOfWork and IDisposal the CreateUser looks like this:
public MembershipCreateStatus CreateUser(string username, string password, string email, bool autoemail, string fullname)
{
using (TransactionScope tran = new TransactionScope())
{
using (TemplateEntities ctx = new TemplateEntities())
{
UserRepository rep = new UserRepository(ctx);
//OtherRepository rep2 = new OtherRepository(ctx);
if (rep.GetUser(username) != null)
return MembershipCreateStatus.DuplicateUserName;
if (requiresUniqueEmail && !String.IsNullOrEmpty(rep.GetUserNameByEmail(email)))
return MembershipCreateStatus.DuplicateEmail;
User userToCreate = new User
{
UserName = username,
PassWord = EncodePassword(password),
FullName = fullname,
Email = email,
AutoEmail = autoemail
};
try
{
rep.AddUser(userToCreate);
ctx.SaveChanges();
tran.Complete();
return MembershipCreateStatus.Success;
}
catch
{
return MembershipCreateStatus.UserRejected;
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这看起来基本没问题。但有一些建议:
TemplateEntities
。这样做的原因是,当您在一个事务中需要两个存储库时,就会遇到问题。您应该将处理TemplateEntities
的责任移至与TransactionScope
相同的级别;TransactionScope
应移至更高级别。最好,TemplateEntities
应该在TransactionScope
内实例化;Save
包装器不包含功能,则不必创建它。如果您在IUnitOfWork
接口上指定void SaveChanges()
,这将获取TemplateEntities
的SaveChanges
;string GetUserNameByEmail(...)
而是使用User GetUserByEmail(...)
因为这样也可以满足您的目的,并且您的优势是不当您稍后需要User GetUserByEmail(...)
时,有两种按电子邮件地址搜索的方法;ctx
设为私有,或者至少将其设置为私有 setter,例如public TemplateEntities Ctx { get;私人套装; }
;-
This looks basically OK. A few suggestions though:
TemplateEntities
. The reason for this is that when you need two repositories within one transaction, you have a problem. You should move the responsibility of disposing theTemplateEntities
to the same level as theTransactionScope
;TransactionScope
should be moved to a higher level. Preferably, theTemplateEntities
should be instantiated within aTransactionScope
;Save
wrapper if it does not contain functionality. If you specify thevoid SaveChanges()
on theIUnitOfWork
interface, this will pick up theSaveChanges
of theTemplateEntities
;string GetUserNameByEmail(...)
but ratherUser GetUserByEmail(...)
because then this will also serve your purpose and you have the advantage of not having two methods that search by e-mail address when you later need theUser GetUserByEmail(...)
;ctx
private, or at least a private setter likepublic TemplateEntities Ctx { get; private set; }
;-