2010-10-24 105 views
1

我觉得我做错了什么在这里,所以我会在这里贴上这样你就可以把我在正确的轨道:我是否处理好数据库连接(实体框架)?

 public MembershipCreateStatus CreateUser(string username, string password, string mail, bool autoemail, string fullname) 
     { 
      using (TemplateEntities ctx = new TemplateEntities()) 
      { 
       using (TransactionScope tran = new TransactionScope()) 
       { 
        if (GetUser(username)!=null) 
         return MembershipCreateStatus.DuplicateUserName; 
        if (requiresUniqueEmail && !String.IsNullOrEmpty(GetUserNameByEmail(email))) 
         return MembershipCreateStatus.DuplicateEmail;      
        User userToCreate = new User 
        { 
         UserName=username, 
         PassWord=EncodePassword(password), 
         FullName=fullname, 
         Email=email, 
         AutoEmail=autoemail 
        }; 
        try 
        { 
         ctx.Users.AddObject(userToCreate); 
         ctx.SaveChanges(); 
         tran.Complete(); 
         return MembershipCreateStatus.Success; 
        } 
        catch 
        { 
         return MembershipCreateStatus.UserRejected; 
        } 
       } 
      } 
     } 

     public override string GetUserNameByEmail(string email) 
     { 
      using (TemplateEntities ctx = new TemplateEntities()) 
      { 
       return (from u in ctx.Users 
         where u.Email == email 
         select u.UserName).SingleOrDefault(); 
      } 
     } 

     public User GetUser(string username) 
     { 
      using (TemplateEntities ctx = new TemplateEntities()) 
      { 
       return (from u in ctx.Users 
          where u.UserName == username 
          select u).FirstOrDefault(); 
      } 
     } 
  1. 1Q)我开到数据库3个 连接。它是 好吗?或者我必须只有一个 连接以及如何正确管理该 ?
  2. 2Q)我需要交易吗? 如何正确管理?

回答

1

Re 3 connections;你可能想让这些方法知道数据上下文,或者通过传递它作为参数,或者使用部分类或扩展方法将数据上下文添加到(假设它是相同类型的数据每次上下文)。这将最大化连接重用和对象身份重用。

重新交易;提交应该已经是事务性的。那么问题是,我是否需要在同一个事务中读取数据。这取决于:)通常没关系,但你可以得到幻像读取等问题。做一个可序列化事务内的读取(像你一样)确保读取数据不会改变,直到事务提交。这可能会对吞吐量产生负面影响(特别是在分布式事务涉及的情况下,因此希望最大化连接重用),并且(在某些情况下,除非发布UPDLOCK)会引入额外的死锁。

所以这是一个权衡。这取决于你的具体情况。

作为一个例子重写那些在上下文中传递:

public override string GetUserNameByEmail(TemplateEntities ctx, string email) 
{ 
    return (from u in ctx.Users 
      where u.Email == email 
      select u.UserName).SingleOrDefault(); 
} 

public User GetUser(TemplateEntities ctx, string username) 
{ 
    return (from u in ctx.Users 
      where u.UserName == username 
      select u).FirstOrDefault(); 
} 

现在你可以在你的情况下通过;

public User GetUser(string username) 
{ 
    using(var ctx = new TemplateEntities()) { return GetUser(ctx, username);} 
} 
+0

谢谢您的回复,通过上下文作为参数传递给这两个方法意味着我将有一个连接:如果你想仍然提供此作为一个选项,而不传递明确的环境下,你也许可以重载方法并且SaveChanges在事务中执行。你说的话很有道理,谢谢你的回复。 – gigi 2010-10-24 09:10:35

+0

@gigi - 请注意,这不仅仅是重要的SaveChanges;例如,重复的电子邮件/用户名检查;如果那些**在同一次交易中不是**,那么您将面临竞争状况。我会建议在DB处强制执行,哪个(与支票相结合)给出合理的折中。 – 2010-10-24 09:12:48

+1

我同意,在上下文中传递。或者更好的是,隐藏在存储库和工作单元的后面(这是在通话之间共享上下文的更优雅的方式) – RPM1984 2010-10-24 09:15:57