2010-10-24 23 views
9

Tôi tìm thấy một số ví dụ về cách tạo đơn vị công việc với ef4, tôi không sử dụng di/ioc và tôi muốn giữ mọi thứ đơn giản và ví dụ này (90% lấy cảm hứng) và tôi nghĩ không sao nhưng vì tôi đang nhìn vào một mô hình để sử dụng từ bây giờ tôi muốn hỏi ý kiến ​​một lần cuối cùng.Tôi có sử dụng đúng Đơn vị công việc ở đây không? (Entityi Framework 4 POCO)

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(); 
    } 
} 

Và cuối cùng

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; 
        } 
       } 
      } 
     } 
    } 

Sau khi loại bỏ nếu IUnitOfWork và IDisposal các CreateUser trông như thế này:

 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; 
        } 
       } 
      } 
     } 

Trả lời

2

này trông cơ bản OK. Một vài đề xuất mặc dù:

  • Bạn không nên để kho lưu trữ xử lý TemplateEntities. Lý do cho điều này là khi bạn cần hai kho lưu trữ trong một giao dịch, bạn có một vấn đề. Bạn nên chuyển trách nhiệm xử lý TemplateEntities đến cùng mức với TransactionScope;
  • Các TransactionScope phải được chuyển lên cấp cao hơn. Tốt hơn là, TemplateEntities nên được khởi tạo trong một TransactionScope;
  • Bạn không phải tạo trình bao bọc Save nếu nó không chứa chức năng. Nếu bạn chỉ định void SaveChanges() trên giao diện IUnitOfWork, điều này sẽ nhận số SaveChanges của số TemplateEntities;
  • Cá nhân tôi sẽ không có string GetUserNameByEmail(...) nhưng thay vì User GetUserByEmail(...) vì điều này cũng sẽ phục vụ mục đích của bạn và bạn có lợi thế là không có hai phương pháp tìm kiếm theo địa chỉ e-mail khi bạn cần User GetUserByEmail(...);
  • Bạn có thể muốn suy nghĩ về việc thực hiện ctx riêng tư hoặc ít nhất một người đặt riêng tư như public TemplateEntities Ctx { get; private set; };
  • Bạn có thể tạo một kho lưu trữ trừu tượng với các phương pháp như ví dụ bên dưới. Điều này sẽ giúp bạn tiết kiệm rất nhiều cách gõ ngu si đần độn trong thời gian dài:

-

public interface IRepository<TEntity> 
{ 
    void Delete(TEntity entity); 

    /* ... */ 
} 

public abstract class AbstractRepository<TEntity> : IRepository<TEntity> 
{ 
    public TemplateEntities ctx; 

    public AbstractRepository(IUnitOfWork unit) 
    { 
     ctx = unit as TemplateEntities; 
    } 

    protected abstract ObjectSet<TEntity> Entites { get; } 

    public virtual void Delete(TEntity entity) 
    { 
     Entities.Attach(entity); 
     ctx.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Deleted); 
    } 

    /* ... */ 
} 

public interface IUserRepository : IRepository<User> 
{ 
    User GetUser(string username); 

    /* ... */ 
} 

public class UserRepository : AbstractRepository<User>, IUserRepository 
{ 
    public UserRepository(IUnitOfWork unit) 
     : base(unit) 
    { 
    } 

    protected override ObjectSet<User> Entites 
    { 
     get { return ctx.Users; } 
    } 

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

    /* ... */ 
} 
+0

Bạn nghĩ rằng tôi nên thoát khỏi giao diện IUnitOfWork? – gigi

+0

Tôi không biết, có thể. Tôi không thấy giá trị gia tăng với thiết lập này. Thông thường, bạn sẽ thêm một lớp trừu tượng bổ sung khi bạn, ví dụ: có hai cơ sở dữ liệu được quản lý bởi đơn vị công việc. Sau đó, kho lưu trữ sẽ nhận được bối cảnh của mình từ đơn vị công việc. Về cơ bản, 'TemplateEntities' đã là một đơn vị công việc. –

+0

Tôi sẽ dán trong bài đăng của tôi phương pháp CreateUser mới để bạn có thể cho tôi biết nếu nó là cách tốt hơn. Tôi mong được trả lời của bạn. – gigi

Các vấn đề liên quan