سؤال

لقد وجدت بعض الأمثلة على كيفية إنشاء وحدة العمل مع 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;
                    }
                }
            }
        }
هل كانت مفيدة؟

المحلول

هذا يبدو على ما يرام بشكل أساسي. بعض الاقتراحات على الرغم من:

  • يجب ألا تدع المستودع يتخلص من TemplateEntities. والسبب في ذلك هو أنه عندما تحتاج إلى مستودعين في معاملة واحدة ، لديك مشكلة. يجب عليك تحريك مسؤولية التخلص من TemplateEntities إلى نفس مستوى TransactionScope;
  • ال TransactionScope يجب نقلها إلى مستوى أعلى. ويفضل ، و TemplateEntities يجب إنشاء مثيل له ضمن أ TransactionScope;
  • ليس عليك إنشاء Save غلاف إذا لم يحتوي على وظيفة. إذا قمت بتحديد void SaveChanges() على ال IUnitOfWork الواجهة ، هذا سوف يلتقط SaveChanges التابع TemplateEntities;
  • شخصيا لن يكون لدي string GetUserNameByEmail(...) لكن بالأحرى User GetUserByEmail(...) لأن هذا سيخدم هذا الغرض أيضًا ولديك ميزة عدم وجود طريقتين تبحث عن عنوان البريد الإلكتروني عندما تحتاج لاحقًا إلى User GetUserByEmail(...);
  • قد ترغب في التفكير في صنع ctx خاص ، أو على الأقل معدي خاص مثل public TemplateEntities Ctx { get; private set; };
  • يمكنك إنشاء مستودع مجردة مع طرق مثل المثال أدناه. سيوفر لك هذا الكثير من الكتابة المملة على المدى الطويل:

-

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

    /* ... */
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top