WPF/MVVM 应用程序中的数据访问使用啥模式
Posted
技术标签:
【中文标题】WPF/MVVM 应用程序中的数据访问使用啥模式【英文标题】:What pattern to use for Data Access in WPF/MVVM AppWPF/MVVM 应用程序中的数据访问使用什么模式 【发布时间】:2011-06-22 23:32:39 【问题描述】:我有一个任务管理应用程序,它当前使用一个类来使用 Linq-to-SQL 访问数据;我想将数据访问移至项目中的单独解决方案。我想这样做的原因是为两件事做准备。首先是创建一个将在数据库“服务器”(它只是一台 win 7 PC)上运行的服务,该服务将定期查询任务并为到期的任务发送电子邮件提醒。其次是更改对 WCF 的数据访问,以便我可以从 WP7 访问任务(一旦它们在 Verizon 上)
返回的任务由绑定到视图模型的许多用户控件定义。目前,iQueryable 是在一系列语句中构建的,这些语句根据数据绑定成员缩小选择范围。然后查询由其他成员排序。一旦我将数据访问移出解决方案,使其无法访问 viewmodels 成员,我将需要传递相对大量的参数,并且我不确定执行此操作的正确方法是什么。我能想到的方法是:
-
只需创建一个包含十几个或更多参数的方法(有人告诉我这是不好的做法)
创建一个包含所有参数的对象并传递它(与我的第一个选项似乎没有太大不同)
在数据访问解决方案中创建一个类,然后实例化它并设置它的每个属性,然后调用将返回 iQueryable(或 ObservableCollection)的方法,但我读到这种做法“味道不好”
我对 OOP 和 WPF 非常熟悉,这个简单的应用程序是我构建的最复杂的应用程序。我觉得我缺少一个模式或实践,建议?
如何构建查询的示例:
IQueryable<Issue> issuesQuery;
// Will select all items
issuesQuery = from i in db.Issues
select i;
// Filters out pending issues
issuesQuery = issuesQuery.Where(i => i.IssIsPending == showPendingTasks);
// Filters out closed issues if they are not to be shown
if (includeClosedIssues == false)
issuesQuery = issuesQuery.Where(i => i.IssIsClosed == false);
// Filters out Regular Tasks if they are not to be shown
if (showTasks == false)
issuesQuery = from i in issuesQuery
where i.IssIsOnStatusBoard == true
select i;
// More filters are here
// Order the results
issuesQuery = issuesQuery.OrderByDescending(
i => i.IssIsSticky).ThenBy(
i=>!i.IssDueDate.HasValue).ThenBy(
i => i.IssDueDate).ThenBy(
i => i.IssUrgency);
// an iQueryable is returned but is then converted to an ObservableCollection
return issuesQuery;
【问题讨论】:
其实第二点(带参数的对象)比较好,因为: 1)你可以添加或删除参数,方法仍然与其他客户端兼容; 2) 可以只设置必要的参数并使用默认值传递对象。但是我还没有理解第 3 点,如果对您来说没有太大的麻烦,您能否提供代码或文章的链接?您还可以查看 WCF 数据服务,但它们并不总是比常见的 WCF 服务更好。 在第三种方法中,我将创建一个公共类,其中包含所有参数的成员和一个返回集合的方法。要使用它,您将实例化它,设置所有成员然后调用方法(这将使用成员的值来确定要返回的项目) 我几周前刚购买了 John Sharps “Windows Communication Foundation 4”,但由于生日 Kindle 的原因延迟了启动它:) 我目前对此知之甚少 【参考方案1】:我将向您解释如何使用服务,因为它们在 3-tired 架构中是强制性的,并且无法将模型与视图分开。
您可以使用两种不同的解决方案。
1. WCF 数据服务。
添加 -> 新项目 -> Wcf 数据服务。
然后指定DataContext的名称并设置访问权限。
public class WcfDataService1 : DataService<TestEntities>
public static void InitializeService(DataServiceConfiguration config)
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
/// <summary>
/// Example of custom operations
/// </summary>
[WebGet]
public IQueryable<Item> ItemsById(int id)
return this.CurrentDataSource.Items.Where(i => i.Id == id);
在客户端应用程序中添加一个新的服务引用,然后您可以像使用本地数据库一样使用该服务:
var proxy = new TestEntities(new Uri("http://localhost:8513/WcfDataService1.svc/"));
var items = proxy.Items.Where(i => i.Id > 2 && i.Title.Contains("x1"));
var item2 = proxy.Execute<Item>(new Uri("ItemsById?Id=1", UriKind.Relative)).FirstOrDefault();
优点:无需编写GetItemsById、GetItemsByYear、GetTenItems等众多方法;您可以在客户端创建过滤查询。
缺点:服务操作不是静态类型的;调用自定义操作很困难,尤其是在有很多参数的情况下;如果使用自定义对象而不是实体,会有很多问题;
2。 WCF 服务
添加 -> 新项目 -> Wcf 服务
存储库类:
public class IssuesRepository
public static List<Issue> GetIssues()
//creating a new connection will not cause overhead because there is a pool of connections
using (var db = new TestEntities())
List<Expression<Func<Issue, bool>>> filters = new List<Expression<Func<Issue, bool>>>();
filers.Add(i => i.IssIsPending == showPendingTasks);
if (includeClosedIssues == false)
filers.Add(i => i.IssIsClosed == false);
if (showTasks == false)
filers.Add(i => i.IssIsOnStatusBoard == true);
IQueryable<Issue> issuesQuery = db.Items.AsQueryable();
foreach (var filter in filters)
issuesQuery = issuesQuery.Where(filter);
issuesQuery = from i in issuesQuery
orderby i.IssIsSticky descending, !i.IssDueDate.HasValue ascending, i.IssDueDate, i.IssUrgency
select i;
return issuesQuery.ToList(); //it will be serialized in any case
服务:
public class Service1 : IService1
public List<Issue> GetIssues()
return IssuesRepository.GetIssues();
优点:独立于协议;提供会话、安全性、事务。
因此,作为一个结论,如果您只需要一个 CRUD 功能,我建议使用 DataServices,如果您使用一组具有复杂逻辑的操作,我建议使用通用 WCF 服务。
【讨论】:
哇,感谢您的回复。看来我有一些功课要做。 @Mike B 只需阅读本书并编写一些测试应用程序即可更熟悉 WCF。之后很多事情都会变得简单。以上是关于WPF/MVVM 应用程序中的数据访问使用啥模式的主要内容,如果未能解决你的问题,请参考以下文章