Question

J'ai trouvé quelques exemples de la façon de créer l'unité de travail avec EF4, je n'ai pas utilisé di / cio et je voudrais garder les choses simples et cela un exemple (90% d'inspiration) et je pense qu'il est ok, mais depuis que je je regarde un modèle à utiliser à partir de maintenant je voudrais demander un avis, une dernière fois.

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

Et enfin

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

Après s'être débarrassé si le IUnitOfWork et IDisposal l'CreateUser ressemble à ceci:

        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;
                    }
                }
            }
        }
Était-ce utile?

La solution

Cela ressemble fondamentalement OK. Quelques suggestions cependant:

  • Vous ne devriez pas laisser le dépôt disposer les TemplateEntities. La raison en est que lorsque vous avez besoin de deux dépôts dans une transaction, vous avez un problème. Vous devez déplacer la responsabilité de disposer du TemplateEntities au même niveau que le TransactionScope;
  • Le TransactionScope doit être déplacé à un niveau supérieur. De préférence, le TemplateEntities doit être instancié dans un TransactionScope;
  • Vous ne devez pas créer l'emballage de Save si elle ne contient pas de fonctionnalité. Si vous spécifiez le void SaveChanges() sur l'interface IUnitOfWork, cela va prendre le SaveChanges du TemplateEntities;
  • Personnellement, je n'aurais pas string GetUserNameByEmail(...) mais User GetUserByEmail(...) car alors cela aussi servir votre but et vous avez l'avantage de ne pas avoir deux méthodes qui recherche par adresse e-mail lorsque vous avez besoin plus tard, le User GetUserByEmail(...);
  • Vous voudrez peut-être penser à faire ctx privé, ou au moins un setter privé comme public TemplateEntities Ctx { get; private set; };
  • Vous pouvez créer un référentiel abstrait avec des méthodes comme l'exemple ci-dessous. Cela vous fera économiser beaucoup de dactylographie terne à long terme:

-

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

    /* ... */
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top