[译]WCF RIA Services中的集合(1)

原文地址:http://www.silverlightshow.net/items/Working-with-collections-in-WCF-RIA-Services-part-one.aspx

本文分为两部分,本篇为第一部分。

介绍

今天,很多的商业应用是使用WCF RIA Services构成的(这并不奇怪,它确实是一个强大的高扩展性框架)。然而它对集合类型的支持可以变得更好。你经常会做这样的操作:获取实体(通常是一个Load Operation)在其完成事件中将其添加到一个ObservableCollection<T>中,现在你依然可以这样做。不过在WCF RIA Services的第一个SP中分别对一些之前就存在的集合类型进行了加强,同事也增加了一些新的集合类型。这些变化使你在使用WCF RIA Services配合MVVM模式时更得心应手。现在我们可用的集合可以自动跟踪你的DomainContext,你可以添加过滤、排序甚至分组条件,还提供了一个服务端可分页的DomainCollectionView。在这篇文章中,我们会一起探讨一下这些增强及新增的新集合类型以及看看它们在哪些场景中使用起来更给力。

本文中将会涉及WCF RIA Services中的四种集合类型:EntitySet(增强)、EntityList(新增)、CollectionView(增强)以及DomainCollectionView(新增)。你可以在这里下载源码

WCF RIA Services SP1包含在Visual Studio 2010 SP1中,点此下载

EntitySet<T>

EntitySet是WCF RIA Services应用程序中的一个基本集合类型—当我们建立ViewModel时会经常用到它。它是一个带有一些用来自定义返回类型选项的无序集合。因此当我们想查看通过DomainContext载入的某个类型的所有实体时,我们会经常使用它。

下图是一个示例程序,我将Books属性绑定到ListBox上。

clip_image002

看下面的代码:

/// <summary>
/// The Books property
/// </summary>
public EntitySet<Book> Books{
    get{
        return Context.Books;
    }
}

像你看到的那样,Books属性是一个Book类型的EntitySet集合,它只是Context.Books的简单引用。在构造函数中,我们载入10条数据:

public EntitySetViewModel() {

    InstantiateCommands();

    // load books
    Context.Load<Book>(Context.GetBooksQuery().Take(10));
}

当需要更多数据时,这样

LoadMoreBooks = new RelayCommand(() => {
    Context.Load<Book>(Context.GetBooksQuery());
});

当更多的Book类型的实体被添加到正确的Context.Books这个EntitySet时,这些新增的Books也被加载到ListBox中。换句话说,当Book数据被DomainContext载入时,它们也被同时添加到ContextBooks这个EntitySet中了。

EntitySet<T>:添加和移除数据

那么如何向EntitySet添加或移除数据呢?下面的代码展示如何添加数据:

AddBook = new RelayCommand(() => {
    Context.Books.Add(new Book() {
        Author = "Kevin Dockx"
        ,
        ASIN = "123456"
        ,
        Title = "Dummy book"
    });
});

然后是移除数据:

DeleteBook = new RelayCommand(() => {
    Context.Books.Remove(Context.Books.FirstOrDefault());
});

当你调用SubmitChanges()方法时,DomainService会将增加/删除的数据切实的反映为服务端的相应操作。

EnityList<T>

下一个要介绍的集合类型是:EntityList<T>,它是一个新增的集合类型,你可以在WCF RIA Services Toolkit中找到它,它位于Microsoft.Windows.Data.DomainServices命名空间下(源码中已经包含了这个程序集)。本质上说它是一个基于EntitySet的Observable集合。它的优点是允许我们取得通过DomainContext载入的特定类型实体数据的子集。定义一个EntityList<T>属性大概是如下的样子:

private EntityList<Book> _books;
public EntityList<Book> Books {
    get {
        if (this._books == null) {
            this._books = new EntityList<Book>(
                this.Context.Books);
        }
        return this._books;
    }
}

Entity List有一个Source属性,它定义了EntityList应该包含的实体:

public EntityListViewModel() {
    InstantiateCommands();

    // load books
    this.Books.Source = Context.Load<Book>(Context.GetBooksQuery().Take(10)).Entities;
}

通过这两段代码,你的EntityList就已经初始化并准备好了。

一旦你开始读取更多的Book类型实体,事情就变得有趣起来了:数据变化不会自动的反映到你的EntityList中。如果你想让EntityList对那些新增的Book作出反应,则需要设置它的Source属性:

LoadMoreBooks = new RelayCommand(() => {
    this.Books.Source = Context.Load<Book>(Context.GetBooksQuery()).Entities;
});

EntityList<T>:添加和移除数据

添加一条新的Book实体通常通过两种方式,直接添加到Context中或添加到EntityList本身。这两种方式需要使用不同的方法处理。可以看到我们示例中的代码:

AddBook = new RelayCommand(() => {
    Context.Books.Add(new Book() {
        Author = "Kevin Dockx"
        ,
        ASIN = "123456"
        ,
        Title = "Dummy book"
    });
});

一条新的Book被添加到Context中。不过EntityList不会自动的获知这些变化(上文说过,实现项的子集的变化跟踪需要通过设置Source属性,而非每次Context的载入变化),ListBox仍然显示EntityList的Source属性中的实体数据集合。

当如下代码执行时:

AddBookToEntityList = new RelayCommand(() => {
    Books.Add(new Book() {
        Author = "Kevin Dockx"
        ,
        ASIN = "123456"
        ,
        Title = "Dummy book"
    });
});

一条新的Book实体被添加到EntityList中,这将直接反映到我们的ListBox控件中。如果EntitySet中不存在这条Book实体,则它会被同时添加到其对应的EntitySet中。

而移除一条Book的行为又有一些不同:当你从Context的EntitySet中移除Book数据的时候,它会直接反映到EntityList中:

DeleteBook = new RelayCommand(() => {
    Context.Books.Remove(Context.Books.FirstOrDefault());
});

当你从EntityList中移除一条Book时,EntitySet中也会同时移除这条实体。

DeleteBookFromEntityList = new RelayCommand(() => {
    Books.Remove(Books.FirstOrDefault());
});

这是本文的第一部分,第二部分将会对更高级的集合类型进行介绍,他们是:ICollectionView和DomainCollectionView,敬请期待。

posted @ 2011-07-15 16:05 紫色永恒 阅读(...) 评论(...) 编辑 收藏