在WPF应用程序中管理DbContext

时间:2016-02-09 20:30:29

标签: c# .net wpf entity-framework

我目前正在使用.NET 4.6开发WPF应用程序。我们使用实体框架进行持久性和数据库与SQL Server的交互。当我加入项目时,所有数据库交互都在后面的代码中完成,如下所示。 (是的,我意识到这是不好的做法)

IList<User> users;
using (AppDbContext db = new AppDbContext())
{
    users = db.Users.Where(x => x.Active == true).ToList();
}

// do code to update UI

我基本上说这是不好的做法,我们需要从表示层中分离出业务逻辑和查询。我认为Repository模式可能是一个很好的起点,但我对如何管理DbContext有疑问。

示例存储库接口

public interface IUserService : IDisposable
{
    IList<applicationuser> GetUsers();
    IList<AllApplicationUser> GetActiveUsers();
    AllApplicationUser GetUserView(long id);
    applicationuser GetUser(long id);
    void CreateUser(applicationuser user);
    void UpdateUser(applicationuser user);
    void DeleteUser(long id);
    void Save();
    applicationuser Authenticate(string username, string password);
}

实施

class UserService : IUserService
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        private readonly OMEGAEntities _db;
        private bool _disposed = false;

        public UserService()
        {
            _db = new OMEGAEntities();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _db.Dispose();
                }
            }
            _disposed = true;
        }

        public IList<applicationuser> GetUsers()
        {
            // fetch only active users that do not have the role SuperAdmin
            return _db.applicationusers.Where(u => u.roleid != 1 && u.activeflag == true).ToList();
        }

        public IList<AllApplicationUser> GetActiveUsers()
        {
            return _db.AllApplicationUsers.Where(u => u.activeflag == true && u.roleid != 1).ToList();
        }

        public AllApplicationUser GetUserView(long id)
        {
            return _db.AllApplicationUsers.Single(x => x.id == id);
        }

        public applicationuser GetUser(long id)
        {
            return _db.applicationusers.Find(id);
        }

        public void CreateUser(applicationuser user)
        {
            _db.applicationusers.Add(user);
        }

        public void UpdateUser(applicationuser user)
        {
            _db.Entry(user).State = EntityState.Modified;
        }

        public void DeleteUser(long id)
        {
            var user = _db.applicationusers.Find(id);
            _db.applicationusers.Remove(user);
        }

        public void Save()
        {
            _db.SaveChanges();
        }

        public applicationuser Authenticate(string username, string password)
        {
            applicationuser user =
                _db.applicationusers.SingleOrDefault(u => u.loginid.ToLower().Equals(username.ToLower()));

            if (user != null)
            {
                if (Common.Utils.DecryptData(user.password).Equals(password))
                {
                    return user;
                }          
            }

            return null;
        }
    }

现在的问题是,当打开多个窗口时,会打开多个上下文和长时间运行的上下文。现在浮出水面的一个想法是为整个应用程序使用单个上下文,因为它是一个单用户桌面应用程序,但这似乎不是最好的主意。此外,当窗口关闭等时,需要关闭dbContexts。

我已经读过在ASP.NET中按请求使用DbContext的想法。也许每个窗口都可以使用一个?

我只是想知道存储库模式是否是WPF应用程序的最佳方式?我见过许多人在ASP.NET中取得了成功。

2 个答案:

答案 0 :(得分:0)

您可以在存储库之上创建一种单元工作,并且构造函数将dbcontext注入存储库

public class UnitOfWork : IUnitOfWork
{
    private IUserService userService;
    private omegaentities dbcontext;
    public UnitOfWork ()
    {
    dbcontext = new Omegaentities ();
    }
    public IUserService UserService {
    get {
             If (userService == null)
             { userService = new UserService(dbcontext);}

    Return userService;
    }

}

然后你打电话

unitOfWork.UserService.GetUsers();

... 这给了一层抽象,你仍然需要处理单元工作的单个实例,但是这可以通过一些DI魔法很好地处理:)

注意:我是从Android应用程序写的! (在手机上编码c#,不会摇滚!)

答案 1 :(得分:-1)

这实际上取决于你如何使用你的DbContext。如果您正在阅读某些其他应用程序可能会更改某些数据,我建议每次都使用一次性DbContext。如果您确定您的应用程序是唯一触及数据库的应用程序,那么在您的存储库中保留一个DbContext并在整个应用程序中使用单例存储库。