4

在过去的几个月里,我一直在使用ADO.Net Data Services (Astoria)进行学习,虽然我喜欢这项技术,但学习是一次真正的尝试。您需要有效使用它们的信息散布在 MSDN 文档、文章、博客文章、支持论坛,当然还有 StackOverflow 中。这个问题是我分享一些来之不易的发现的地方,以便其他人可以受益。我也希望其他人贡献他们的最佳实践和常见问题解答,并纠正我的误解!

为了全面披露,我一直在使用带有 Linq to SQL 的框架,只是为了让我的生活更加复杂,所以我希望我的答案中的细节也适用于实体框架。

首先是一些我发现必不可少的链接。然后,我会将主题特定位放在答案部分。

有用的链接

4

3 回答 3

2

服务运营

有时,能够查询数据并执行简单的更新或创建是不够的——您可能想要实现一些业务逻辑或一些复杂的查询创建,而这在 URI 方案中是不可能的。数据服务通过服务操作以非常基本的形式支持这一点。

这些允许您向服务添加方法,但有一些限制:

  1. 您只能使用基本类型或实体类型(即服务已经公开的类型)。
  2. 方法参数只能是可以表示为 URL 一部分的简单类型。
  3. datasvcutil 不会为服务操作生成任何代码,因此您需要自己将它们添加到客户端库中。
  4. 如果您返回一个实体类型但没有任何内容要返回,即结果为空,那么您将得到一个 404 作为 HTTP 响应。
  5. 如果您返回 void,您将无法使用客户端数据上下文来发出请求,您将不得不使用 WebRequest。

示例(好的,这些已简化,因此实际上不需要是服务操作):

[WebGet]
public Product GetProductByID(int productID)
{
    return this.CurrentDataSource.Products.First(p => p.ID == productID);
}

[WebGet]
public IEnumerable<Product> GetCancelledProducts(int productID)
{
    return this.CurrentDataSource.Products.Where(p.Cancelled);
}
于 2009-10-06T17:05:35.123 回答
1

Silverlight 客户端库

LINQ 查询

起初,您的上下文中似乎无法使用 linq 语法,因为所有查询都是异步的,并且 IEnumerable 显然没有 BeginExecute 方法。要使用 Linq 语法,您需要转换最终查询:

var query = (DataServiceQuery<Product>)myContext.Products.Where(p => p.SupplierID == 5);
query.BeginExecute(this.HandleQueryResults, query);

注意查询是传入的,这是因为你需要使用相同的 DataServiceQuery 实例来调用 EndExecute,你不能只使用上下文。

更改跟踪

客户端库不会自动跟踪生成类型中的字段更改。为此,您必须在部分类型中实现 INotifyPropertyChanged。

例子:

public partial class Product : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    partial void OnProductIDChanged() { FirePropertyChanged("ProductID"); }
    partial void OnProductNameChanged() { FirePropertyChanged("ProductName"); }

    private void FirePropertyChanged(string property) { ... }
}

在 1.5 版中,数据服务工具可以为您生成此文件,但目前仅在 CTP 中:Silverlight 3 和 1.5 CTP2 中的数据绑定简介

更新的服务器数据

默认情况下,Silverlight 客户端上下文将 MergeOption 设置为 AppendOnly。这意味着一旦您第一次查询实体,您将不会看到任何更改,这是一种缓存和性能优化的形式。要查看更新,您需要将 MergeOption 更改为 OverwriteChanges,这将确保对象已更新。您还可以丢弃上下文并重新创建。

myContext.MergeOption = MergeOption.OverwriteChanges

跨域访问

Silverlight 为 ADO.NET 数据服务 1 生成的类型使用它们自己的网络堆栈来提供更多的请求动词,但不幸的是,这意味着跨域策略不适用,并且您无法发出跨域请求。要解决此问题,您可以代理请求或等待 Silverlight 3 中支持跨域的版本 1.5(CTP 2 当前可用)。

链接:

于 2009-10-06T16:33:29.277 回答
1

使用 Linq to SQL

您可以直接使用 Linq to SQL 作为 Data Services 的只读数据上下文:

public class MyService : DataService<MyLinqToSqlDataContext>

但是,要获得更新/写入支持,您需要为 Linq to SQL 实现 IUpdateable。幸运的是,Andrew Conrad 在 MSDN 代码库中为您准备了一份:

用于 Linq to Sql 的 ADO.Net 数据服务 IUpdateable 实现

将其作为数据上下文的部分类放入,您就可以读写了。请注意,此实现确实在网站上详细介绍了一些小问题,并且有时按照设计使用带有实体框架的数据服务感觉更加无缝。

更新检查

存储更改时,您会看到 Linq to Sql 生成一个 WHERE 子句来检查字段上的现有值,这并不总是您想要的。这实际上是一个 Linq to Sql 技巧,而不是特定于数据服务的,但这是我使用 Linq to Sql 的唯一地方。要停止此行为,请进入 Linq to Sql 设计器并选择您不想检查的字段。将 UpdateCheck 属性更改为 Never 或 OnlyWhenChanged。

于 2009-10-06T16:46:10.157 回答