如何...显示数据库中的数据
How to... Display Data from Database
我现在有一个由两部分组成的应用程序
- 使用 EF 从数据库接收数据的查看器
- 一种在运行时操作数据库数据的服务。
幕后逻辑包括一些项目,例如存储库 - 数据访问是通过一个工作单元实现的。查看器本身是一个带有底层 ViewModel 的 WPF 窗体。
ViewModel 包含一个 ObservableCollection,它是我的 Viewer 的数据源。
现在的问题是 - 我如何能够每隔几分钟检索一次数据库数据?我知道以下两个问题:
这不是我的存储库中的最新数据 "loading" - EF "smart" 是否从本地缓存填充和检索数据?如果是这样,我如何强制 EF 从数据库加载数据?
重新设置整个 ObservableCollection 或从另一个线程/后台工作者(通过调用)添加/删除实体是不可能的。我该如何解决这个问题?
如果需要,我会添加一些我的代码,但目前我认为这根本没有帮助。
编辑:
public IEnumerable<Request> GetAllUnResolvedRequests() {
return AccessContext.Requests.Where(o => !o.IsResolved);
}
这段代码不会获取最新数据 - 我手动编辑了一些行(将 IsResolved 设置为 true),但此方法仍然会检索它。
编辑2:
编辑3:
var requests = AccessContext.Requests.Where(o => o.Date >= fromDate && o.Date <= toDate).ToList();
foreach (var request in requests) {
AccessContext.Entry(request).Reload();
}
return requests;
最后一题:
上面的代码 "solves" 问题 - 但在我看来它并不干净。还有别的办法吗?
当您访问数据库中的实体时,该实体会被缓存(并被跟踪以跟踪您的应用程序所做的更改,直到您指定 AsNoTracking)。
这有一些问题(例如,性能问题,因为缓存增加或您看到的是旧版本的实体)。
出于这个原因,在使用 EF 时,您应该使用工作单元模式(即,您应该为每个工作单元创建一个新的上下文)。
您可以查看这篇 Microsoft 文章以了解如何实施工作单元模式。
http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
在您的情况下,使用 Reload 不是一个好的选择,因为该应用程序不可扩展。对于每次重新加载,您都在对数据库进行查询。如果您只需要 return 所需的实体,最好的方法是创建一个新的上下文。
public IEnumerable<Request> GetAllUnResolvedRequests()
{
return GetNewContext().Requests.Where(o => !o.IsResolved).ToList();
}
您可以执行以下操作。
您可以定义定期检查数据库的任务(它在 ThreadPool 上保持 运行)(考虑到定期让 EF 重新加载数据有其自身的成本)。
并且您可以在查询中定义 SQL Dependency,这样当数据发生变化时,您可以通知主线程。
我现在有一个由两部分组成的应用程序
- 使用 EF 从数据库接收数据的查看器
- 一种在运行时操作数据库数据的服务。
幕后逻辑包括一些项目,例如存储库 - 数据访问是通过一个工作单元实现的。查看器本身是一个带有底层 ViewModel 的 WPF 窗体。
ViewModel 包含一个 ObservableCollection,它是我的 Viewer 的数据源。
现在的问题是 - 我如何能够每隔几分钟检索一次数据库数据?我知道以下两个问题:
这不是我的存储库中的最新数据 "loading" - EF "smart" 是否从本地缓存填充和检索数据?如果是这样,我如何强制 EF 从数据库加载数据?重新设置整个 ObservableCollection 或从另一个线程/后台工作者(通过调用)添加/删除实体是不可能的。我该如何解决这个问题?
如果需要,我会添加一些我的代码,但目前我认为这根本没有帮助。
编辑:
public IEnumerable<Request> GetAllUnResolvedRequests() {
return AccessContext.Requests.Where(o => !o.IsResolved);
}
这段代码不会获取最新数据 - 我手动编辑了一些行(将 IsResolved 设置为 true),但此方法仍然会检索它。
编辑2:
编辑3:
var requests = AccessContext.Requests.Where(o => o.Date >= fromDate && o.Date <= toDate).ToList();
foreach (var request in requests) {
AccessContext.Entry(request).Reload();
}
return requests;
最后一题: 上面的代码 "solves" 问题 - 但在我看来它并不干净。还有别的办法吗?
当您访问数据库中的实体时,该实体会被缓存(并被跟踪以跟踪您的应用程序所做的更改,直到您指定 AsNoTracking)。
这有一些问题(例如,性能问题,因为缓存增加或您看到的是旧版本的实体)。
出于这个原因,在使用 EF 时,您应该使用工作单元模式(即,您应该为每个工作单元创建一个新的上下文)。
您可以查看这篇 Microsoft 文章以了解如何实施工作单元模式。 http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
在您的情况下,使用 Reload 不是一个好的选择,因为该应用程序不可扩展。对于每次重新加载,您都在对数据库进行查询。如果您只需要 return 所需的实体,最好的方法是创建一个新的上下文。
public IEnumerable<Request> GetAllUnResolvedRequests()
{
return GetNewContext().Requests.Where(o => !o.IsResolved).ToList();
}
您可以执行以下操作。
您可以定义定期检查数据库的任务(它在 ThreadPool 上保持 运行)(考虑到定期让 EF 重新加载数据有其自身的成本)。
并且您可以在查询中定义 SQL Dependency,这样当数据发生变化时,您可以通知主线程。