簡體   English   中英

適用於Silverlight 4 + WCF數據服務的IAsyncRepository或IObservableRepository

[英]IAsyncRepository or IObservableRepository for silverlight 4 + WCF Data Services

更新2 :@Enigmativity有一個很好的答案。 我已將其實現為IObservableRepository<T> 我的答案詳情如下。


問:所以我已經改變了大部分問題(參見編輯歷史)如果有人對我的設計進行了評論/驗證/推測,我會喜歡它。 =)

所以通常我的Repos看起來像這樣:

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

但是當談到Silverlight和WCF數據服務時,它會使所有異步的查詢相關數據變得非常煩人。 我必須首先加載父實體異步,然后查詢其子實體異步。

所以我提出了一個IAsyncRepository ,我想知道設計是否正常,是否可以改進,(以及在這里使用Rx是否有意義?)

要解決子實體問題,我計划在調用回調之前加載所有必需的子實體。

我的回購看起來像:

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

您可以像這樣使用repo:

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

你們有什么感想?

問候,基甸

只是一個快速,袖手旁觀的答案。

如何使用.NETReactive Extensions(Rx)

然后,您可以將存儲庫定義為:

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

所有返回的observable都將包含單個值, GetAll除外,它們將具有零或更多。

Rx世界中的Unit類型void 這只是一種不需要定義非通用IObservable接口的方法。

然后你會這樣查詢:

IObservableRepository<Foo> 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<T> where T : class
{
    IObservable<T> GetById(int id);
    IObservable<T[]> GetAll(Func<IQueryable<T>, IQueryable<T>> query);
    IObservable<int> Submit(T[] insertsOrUpdates);
    IObservable<int> Submit(T[] insertsOrUpdates, T[] deletes);
}

現在提交會更好一些:

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

就像我說的,脫下袖口。 :-)

更新問題的時間太長,所以我發布了答案。

所以我實現了這樣:

public interface IObservableRepository<T, TContext>
{
    IObservable<T> GetById(int id);
    IObservable<IList<T>> GetAll(Func<TContext, IQueryable<T>> funcquery);
    IObservable<int[]> SubmitInserts(IList<T> inserts);
    IObservable<int[]> SubmitDeletes(IList<T> deletes);
    IObservable<int[]> SubmitUpdates(IList<T> updates);
    //helpers
    IObservable<int> SubmitInsert(T entity);
    IObservable<int> SubmitDelete(T entity);
    IObservable<int> 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數據服務+實體框架的CRUD函數的實際返回類型是DataServiceResponse 我所做的是循環它們並返回Http狀態代碼。 因此,為CRUD方法返回的int是Http狀態代碼。
  • 加載子實體時,我只是急於加載它們:

     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

請告訴我是否應該在這里提出實際的實施。

對此的任何評論都將很好地=)

謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM