【发布时间】:2014-10-26 08:44:33
【问题描述】:
我已经为此苦苦思索好几天了,但仍然无法确定哪种方法是正确的。
这个问题的目标是WPF,因为与网络应用程序相反,许多在线帖子和文章推荐contextview-model,而不是contextrequest。
我有一个使用Entity-Framework DB first 模型的WPF MVVM 应用程序。
这是我的应用程序中使用的两个模型的示例(由EF Designer 创建):
public partial class User
{
public User()
{
this.Role = new HashSet<Role>();
}
public string ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Role { get; set; }
}
public class Role
{
public Role()
{
this.User = new HashSet<User>();
}
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<User> User { get; set; }
}
我已将如何处理此问题的选择范围缩小到以下几点:
1) 创建一个DataAccess 类,该类在每个方法调用中创建和处理DbContext:
public class Dal
{
public User GetUserById(object userId)
{
using (var db = new DbEntities())
{
return db.User.Find(userId);
db.SaveChanges();
}
}
public void RemoveUser(User userToRemove)
{
using (var db = new DbEntities())
{
db.User.Remove(userToRemove);
db.SaveChanges();
}
}
}
我可以在我的ViewModel 中使用如下:
public class UserManagerViewModel : ObservableObject
{
private readonly Dal dal = new Dal();
// models...
//commands...
}
2) 与方法 1 类似,但没有 Using 语句:
public class Dal : IDisposable
{
private readonly DbEntities db = new DbEntities();
public User GetUserById(object userId)
{
return db.User.Find(userId);
db.SaveChanges();
}
public void RemoveUser(User userToRemove)
{
db.User.Remove(userToRemove);
db.SaveChanges();
}
public void Dispose()
{
db.SaveChanges();
}
}
ViewModel里面的用法是一样的
3) 为每个entity 创建一个repository。看起来与上述选项相同(也有带或不带 using 的困境),但是每个存储库仅包含与其 entity 相关的方法。
Afaik 的用法与我的ViewModel 中的上述相同。
4) 创建一个Unit-Of-Work 类,该类将按需传递适当的Repository:
public class UnitOfWork : IDisposable
{
private DbEntities db = new DbEntities();
private IUserRepository userRepository;
public IUserRepository UserRepository
{
get
{
return userRepository ?? new UsersRepository(db);
}
}
public void Save()
{
db.SaveChanges();
}
public void Dispose()
{
db.Dispose();
}
}
并在我的ViewModel 中使用它,如下所示:
public class UserManagerViewModel : ObservableObject
{
private readonly UnitOfWork unit = new UnitOfWork();
// models...
//commands...
}
上述哪种方法(如果有)在数据并发性、更好的抽象和分层以及整体性能方面更受欢迎?
编辑 - 在 @987654321 中找到以下段落@:
使用 Windows Presentation Foundation (WPF) 或 Windows 窗体时,请为每个窗体使用一个上下文实例。这使您可以使用上下文提供的更改跟踪功能。
但是,它提出了一个问题,即我应该在我的view-model 中创建一个DbContext 对象还是拥有一个实用程序类(例如我的DAL 类并引用它)更好。
【问题讨论】:
-
EF 拥有出色的 UoW(上下文)+ 存储库(DbSet)。为什么要创建自己的?这些额外的层几乎没有帮助。它们倾向于导致以数据为中心的应用程序将业务逻辑拉入客户端,而不是以任务为中心的应用程序将用例封装在接近 EF 模型的服务中。它是抽象数据与抽象任务(抽象意味着隐藏持久性实现)。
-
@GertArnold 感谢您的回复。由于我特别询问
WPF MVVM,我想知道是否应该使用长寿的DbContext(context每view-model)或者我应该限制我的context的寿命,如选项1(使用using:)) -
两种方法我们都试过了,各有优缺点。没有万能的解决方案,您只需要找出最适合您的解决方案。也就是说,我们决定采用第二种方法并尽可能缩短上下文的生命周期,因为这样可以避免当您有多个 View(想想选项卡或窗口)和多个 ViewModel 并因此同时打开多个上下文时出现问题。
-
通常中间有某种业务逻辑层,看起来像你的 Dal,由 ViewModels 调用。每个业务逻辑操作都会创建一个新的上下文,并使用该上下文完成所有必须做的事情。
标签: c# wpf entity-framework mvvm architecture