适用于Silverlight 4 + WCF数据服务的IAsyncRepository或IObservableRepository

更新2 :@Enigmativity有一个很好的答案。 我已将其实现为IObservableRepository 。 我的答案详情如下。


问:所以我已经改变了大部分问题(参见编辑历史)如果有人对我的设计进行了评论/validation/推测,我会喜欢它。 =)

所以通常我的Repos看起来像这样:

 public interface IRepository where T : class { T GetById(int id); IQueryable GetAll(); void InsertOnSubmit(T entity); void DeleteOnSubmit(T entity); int SubmitChanges(); } 

但是当谈到Silverlight和WCF数据服务时,它会使所有异步的查询相关数据变得非常烦人。 我必须首先加载父实体异步,然后查询其子实体异步。

所以我提出了一个IAsyncRepository ,我想知道设计是否正常,是否可以改进,(以及在这里使用Rx是否有意义?)

要解决子实体问题,我计划在调用回调之前加载所有必需的子实体。

我的回购看起来像:

 public interface IAsyncRepository where T : class { void GetById(int id, Action callback); void GetAllFromQuery(Func<MyEntities, IQueryable> funcquery, Action<IList> callback) } 

您可以像这样使用repo:

 productRepo.GetAllFromQuery( x => x.Products.Where(p => p.ID > 5), y => Assert.IsTrue(y.Count > 0)); //y is a IList 

你们有什么感想?

问候,吉迪恩

只是快速,脱下袖口的答案。

如何使用.NET的Reactive Extensions(Rx) ?

然后,您可以将存储库定义为:

 public interface IObservableRepository where T : class { IObservable GetById(int id); IObservable GetAll(Func, IQueryable> query); IObservable InsertOnSubmit(T entity); IObservable DeleteOnSubmit(T entity); IObservable SubmitChanges(); } 

所有返回的observable都将包含单个值,但GetAll除外,它将具有零或更多。

Rx世界中的Unit类型void 。 这只是一种不需要定义非通用IObservable接口的方法。

然后你会这样查询:

 IObservableRepository repo = ...; var foos = repo.GetAll(ts => ts.Where(t => t.Bar == "Hello")); foos.Subscribe(foo => { // Do something asynchronously with each `Foo`. }); 

提交可以这样做:

 var submit = foos .Select(foo => repo.InsertOnSubmit(foo)).ToArray() .Select(s => repo.SubmitChanges()); submit.Subscribe(result => { // handle the asynchronous result of submit. }); 

这都是基于尝试使存储库方法尽可能接近原始方法,但在Silverlight方面可能需要重构这样的事情:

 public interface IObservableRepository where T : class { IObservable GetById(int id); IObservable GetAll(Func, IQueryable> query); IObservable Submit(T[] insertsOrUpdates); IObservable Submit(T[] insertsOrUpdates, T[] deletes); } 

现在提交会更好一些:

 repo.Submit(foos).Subscribe(result => { // Handle asynchronous result of submit; }); 

就像我说的那样,袖口。 🙂

更新问题的时间太长,所以我发布了答案。

所以我实现了这样:

 public interface IObservableRepository { IObservable GetById(int id); IObservable> GetAll(Func> funcquery); IObservable SubmitInserts(IList inserts); IObservable SubmitDeletes(IList deletes); IObservable SubmitUpdates(IList updates); //helpers IObservable SubmitInsert(T entity); IObservable SubmitDelete(T entity); IObservable SubmitUpdate(T entity); } 

一些说明:

  • GetAll()需要TContext ,实现将具有Entity Framework DataServiceContext ,它允许您执行以下操作:

     var foos = repo.GetAll(ts => ts.Where(t => t.Bar == "Hello")); //ts is a DataContext passed here by GetAll(); 
  • 标记为//helpers的方法只调用其他采用数组的方法。
  • WCF数据服务+entity framework的CRUD函数的实际返回类型是DataServiceResponse 。 我所做的是循环它们并返回Http状态代码。 因此,为CRUD方法返回的int是Http Status Codes。
  • 加载子实体时,我只是急于加载它们:

     context.Products.Expand("Child").Expand("Child2"); 

我基本上可以像这样使用它:

 productRepo.GetById(3).Subscribe(x => /* Do something with product x*/ ); productRepo.SubmitUpdate(product) .Subscribe(r => /*return code should be 204 (http) 201 for insert */); //same for insert and delete 

请告诉我是否应该在这里提出实际的实施。

对此的任何评论都会很好=)

谢谢