silverlight 4 的 IAsyncRepository 或 IObservableRepository + WCF 数据服务

发布于 2024-10-23 13:45:37 字数 1264 浏览 6 评论 0原文

更新2:@Enigmativity 有一个出色的答案。我已将其实现到 IObservableRepository 中。详细信息在我下面的回答中。


问题: 因此,我已经更改了大部分问题(请参阅编辑历史记录),如果有人对我的设计进行评论/验证/呕吐,我会喜欢它。 =)

所以通常我的存储库看起来像这样:

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)
}

您可以像这样使用存储库:

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

你们觉得怎么样?

问候, 吉迪恩

Update 2 : @Enigmativity has a brilliant answer. I've implemented this into a IObservableRepository<T>. Details in my answer below.


Question:
So I've changed most of the question (See edit history) I would just like it if someone commented/validated/puked on my design. =)

So typically my Repos look like this:

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

But when it comes to Silverlight and WCF Data Services, it gets seriously annoying query related data with all the asynchrony. I have to load the parent entity async first and then query its child entities async.

So I came up with an IAsyncRepository, I'd like to know if the design is ok, whether it could be improved, (and whether it makes any sense using Rx here?)

To Solve the child entities problem I plan to load all required child entities before calling the callback.

My Repo looks like:

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)
}

You could use the repo like this:

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

What do you guys think?

Regards,
Gideon

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阳光下的泡沫是彩色的 2024-10-30 13:45:37

只是一个快速、即兴的回答。

如何使用 Reactive .NET (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();
}

所有返回的可观察量都将包含单个值,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;
});

就像我说的,即兴的。 :-)

Just a quick, off the cuff answer.

How about using the Reactive Extensions for .NET (Rx)?

You could then define your repository as:

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();
}

All of the returned observables would contain single values, except for GetAll which would have zero or more.

The Unit type is void in the Rx world. It's just a way of not needing to define a non-generic IObservable interface.

You would then query like so:

IObservableRepository<Foo> repo = ...;

var foos = repo.GetAll(ts => ts.Where(t => t.Bar == "Hello"));

foos.Subscribe(foo =>
{
    // Do something asynchronously with each `Foo`.
});

And submit could be done like this:

var submit =
    foos
        .Select(foo => repo.InsertOnSubmit(foo)).ToArray()
        .Select(s => repo.SubmitChanges());

submit.Subscribe(result =>
{
    // handle the asynchronous result of submit.
});

This is all based on trying to keep the repository methods as close as possible to the original, but it may be worth refactoring on the Silverlight side to something like this:

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);
}

Submit would be a bit nicer now:

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

Like I said, off the cuff. :-)

看透却不说透 2024-10-30 13:45:37

太长了,无法更新问题,所以我发布了答案。

所以我像这样实现它:

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,该实现将具有实体框架DataServiceContext这将允许您执行以下操作:

    var foos = repo.GetAll(ts => ts.Where(t => t.Bar == "Hello"));
    //ts 是通过 GetAll() 传递到此处的 DataContext;
    
  • 标记为 //helpers 的方法仅调用采用数组的其他方法。
  • WCF 数据服务+实体框架的 CRUD 函数的实际返回类型是 DataServiceResponse。我所做的就是循环它们并返回 Http 状态代码。因此,CRUD 方法返回的整数是 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

请告诉我是否应该在此处放置实际的实现。

任何对此的评论都会被很好地接受=)

谢谢

Too long to update the question, so I posted as an answer.

So I implemented it like this:

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);
}

Some notes :

  • TContext is needed for GetAll(), the implementation will have the Entity Framework DataServiceContext which will allow you to do the following:

    var foos = repo.GetAll(ts => ts.Where(t => t.Bar == "Hello"));
    //ts is a DataContext passed here by GetAll();
    
  • The methods marked //helpers just call the other methods that take arrays.
  • The actual return type for CRUD functions for WCF Data Services+Entity Framework is a DataServiceResponse. What I do is loop through them and return the Http Status Codes. So the ints returned for the CRUD methods are Http Status Codes.
  • When loading child entities I just eager loaded them by doing this:

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

I can basically use it like this:

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

Do tell me if I should put up the actual implementation here.

Any comments on this would be well taken =)

Thanks

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文