反应性的扩展.CRUD应用程序示例

本文关键字:应用程序 CRUD 扩展 | 更新日期: 2023-09-27 18:09:27

我刚刚开始掌握响应式扩展,但仍然没有"啊哈"的时刻,当一切似乎都到位的时刻。因此,我需要一些帮助,并且想知道响应式扩展在一个简单的CRUD程序中可能扮演什么样的角色。

有没有人有RX扩展如何帮助他们的CRUD应用程序的例子?正如你所想象的,我正在用c#编写一个CRUD应用程序……任何例子都可以接受,这是张贴的,这样我就可以思考RX如何适合我正在做的编程类型。

也许你可以列出一个编程任务是如何从RX中受益的,以及在使用RX之前该任务是如何完成的。

反应性的扩展.CRUD应用程序示例

我做过这种事情,效果很好:

public interface IStorage : IDisposable
{
    IObservable<int> GetOperationsCount(IScheduler scheduler);
    IObservable<Node> FetchNodes(IObservable<NodeId> nodeIds, IScheduler scheduler);
    IObservable<Node> StoreNodes(IObservable<Node> nodes, IScheduler scheduler);
}

它允许我在后台线程上执行取值和存储,并在UI线程上很容易地返回值给我。

StoreNodes的每次调用也建立一个事务,我可以从返回的可观察对象中获得任何错误。

我还使用GetOperationsCount可观察对象向用户显示挂起操作的数量,等等。

我对Rx的个人经验让我想把它用于任何异步的事情——事件、开始/结束调用、异步、任务、线程等。它使所有内容都适合一个模型,并且可以节省大量代码。

如果你做静态CRUD(获得一个窗口/对话框与创建,读取,更新,写入,无论什么),那么我想它可能只会帮助你的UI。例如,也许你想要某些输入的自动完成功能。或者您必须查询服务以获取要显示的其他信息。那么RX可以帮你做到这一点。它将隐藏许多与异步相关的困难,并为您提供可读的、可以轻松阅读和快速执行的声明式表达式。从这个意义上讲,它就像LINQ一样,只是UI/async

一个典型的CRUD应用程序有一些UI (winform, WPF等)和一个数据存储来获取数据并显示在UI中。这两个组件(UI和数据存储)之间的数据流可以使用Rx建模。

使用Rx我们可以连接两个组件(UI和数据存储),例如:UI可以为Create, Update和Delete公开3个可观察对象(例如:在构造函数中传递给数据存储)。例如:Submit按钮事件可以被映射成Create可观察值,Update和delete也可以。所以基本上数据存储需要订阅这3个可观察对象,而不需要关心数据是如何生成的(这也有助于在UT中轻松创建伪可观察对象)。

Read将是一个简单的读取数据存储的方法,因为它是关于按需提取数据。

所以基本上Rx作为一个抽象来组成这两个组件。

也许我错了,考虑这两个答案。微软倾向于把他们的业务分成很多层,因为他们在这方面有兴趣。

CRUD是物理实现-创建-读取-…但UI似乎是合乎逻辑的-在上下文中-为用户…

有时候你需要有一个层——业务层——来控制进出RDMS的流。在我看来,这太复杂了。

在金融业务中,"更新"或"删除"操作是用新的时间戳复制当前行。这使得清洁手术变得困难——至少在物理上……最重要的是,您可能会认为CRUD只是事务的一部分——在运行中创建"一个逻辑工作单元",直到一切正常——那么您应该执行COMMIT。

希望这将帮助…

CRUD应用程序将具有某种搜索功能。你可以用"输入并等待搜索"来实现一个文本框搜索,就像我最近在博客上写的演示一样:

http://blog.andrei.rinea.ro/2013/06/01/bing-it-on-reactive-extensions-story-code-and-slides/

基本上使用油门和其他响应式扩展,你可以创建一个快速搜索功能。

Rx非常适合集合。现在,我无法想象使用一种没有LINQ功能的语言。

最近,Rx也是一样的,主要是因为LINQ使用了Rx: DynamicData

ReadOnlyObservableCollection<TradeProxy> list;
var myTradeCache = new SourceCache<Trade, long>(trade => trade.Id);
var myOperation = myTradeCache.Connect() 
        .Filter(trade=>trade.Status == TradeStatus.Live) 
        .Transform(trade => new TradeProxy(trade))
        .Sort(SortExpressionComparer<TradeProxy>.Descending(t => t.Timestamp))
        .ObserveOnDispatcher()
        .Bind(out list) 
        .DisposeMany()
        .Subscribe()

基本上,您可以创建类似LINQ的查询,在任何更改后动态刷新自己-源列表中的新项(只需DTO就足够了!),一些属性更改,来自其他地方的信号(作为可观察对象传递)等。

您想要显示带有标志的实体数量吗?一个班轮。

您想根据用户选择的属性轻松显示动态组吗?一个班轮。

要分页吗?3行:P

还有一个叫做ReactiveUI的MVVM框架——它为你提供了一个ReactiveCommand和一些更多的技巧。

其中包括绑定框架和基于lambdas的转换器,在视图中对VM中发生的非常具体的事情做出反应的能力,管理视图模型的激活(如初始命令执行,但不是在构造函数中)。

您希望登录按钮仅在用户和密码不为空时才启用?

Login = ReactiveCommand.CreateFromTask(async () => { /* your async implementation, it can return a value! */}, 
             this.WhenAnyValue(x => x.Username, x => x.Password, (user, psw) => !string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(psw)); // define when the command can execute by providing IObservable<bool>
    Login.Where(x => x == true) // only successful logins, ==true for clarity 
        .InvokeCommand(DisplayMainScreen); // or something

In view你可以这样做:

Login.Where(x => !x).Subscribe(_ =>{ // if login failed, set focus on password and select all text so user can just retype the password
          PasswordBox.SelectAllText(); // can't remember exact methods, but you get the idea
          PasswordBox.SetFocus();
       });

对于你来说,创建"当某事时,做这个"这样的功能变得很自然