【问题标题】:Managing DbContext in WPF Application在 WPF 应用程序中管理 DbContext
【发布时间】:2016-02-09 20:30:28
【问题描述】:

我目前正在使用 .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

我基本上说这是不好的做法,我们需要将业务逻辑和查询从表示层中分离出来。我认为存储库模式可能是一个不错的起点,但我对如何管理 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 中都取得了成功。

【问题讨论】:

  • 不要持久化 DbContexts。曾经。这不是它们的设计方式。在狭窄范围内创建和处置它们(最好使用using 语句)。与它执行的操作的成本相比,创建 DbContext 的成本是微不足道的。不要害怕更新 DbContexts 并经常处理它们。它们很轻,这就是它们的用途。
  • 如果你想在一个中心位置“管理”数据库上下文,就会想到工作单元模式

标签: c# .net wpf entity-framework


【解决方案1】:

您可以在存储库之上创建一种工作单元,然后构造器将 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();

... 这提供了更多的抽象层,您仍然需要处理 unitofwork 的单个实例,但这可以通过一些 DI 魔法很好地处理:)

注意:我是从 android 应用程序中写的! (在手机上编写 c# 代码,不会摇摆不定!)

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 没有。保持一个长期存在的 DbContext 是一个坏主意,并且违背了预期的使用模式。 DbContext 实例应保持尽可能短的时间。如果您要对 DB 执行新操作,请获取新的 DbContext 并在完成后将其丢弃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 2011-02-19
    相关资源
    最近更新 更多