我有一个例程,该例程从db读取数据,并通过IObservable发布该数据。
发布数据后,我想更新所有刚发布的行,以阻止它们再次发布。
我不确定这样做的“反应性”方式。 (每次我重新访问Rx时,我似乎都遇到了这个问题!)
我认为我需要做两件事
1)在发布时缓存数据,因为它将具有我随后需要更新的ID-我想知道是否要使用主题来缓存要发布的数据,或者是否要使用其他一些包裹我的例程当前拥有,订阅它,缓存它,然后重新发布
2)发布数据后更新数据。我真的不确定如何将其构建到管道中!
我已经从网上发现的各种内容中构建了这个数据库(特别是数据库轮询的Lee Campbell-Lee!),但是我添加的其他内容是我的,我可能做得不好错误。如果某些部分可以更好地实现非反应性,我愿意提出建议。例如,我已经使db update例程可观察到,但是我不知道它是否真的必要-或者如果以这种方式实现,是否更容易将其包含在管道中。
下面是相关的代码...
private IObservable<INotification> Poller() =>
Observable
.Timer(_pollingPeriod, _scheduler)
.SelectMany(_ => NewNotifications(_cx))
.Timeout(_pollingPeriod + _queryTimeout, Observable.Return(TimeOut.Notification()), _scheduler)
.Catch<INotification, Exception>(err => Observable.Return(Error.Notification(err)))
.Repeat();
private IObservable<INotification> NewNotifications(string cx)
{
try
{
return SqlRead<INotification>(cx, NewNotificationsSql(),sdr => EventBuilder(sdr), Empty.Notification());
}
catch (Exception ex)
{
throw ex;
}
}
internal static IObservable<T> SqlRead<T>(string cx, string sql, Func<SqlDataReader, T> mapper, T noRows) =>
Observable.Create<T>(o =>
{
using (var conn = new SqlConnection(cx))
{
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
using (var rdr = cmd.ExecuteReader())
{
if (!rdr.HasRows)
{
o.OnNext(noRows);
}
else
{
while (rdr.Read())
{
o.OnNext(mapper(rdr));
}
}
}
}
}
o.OnCompleted();
return Disposable.Empty;
});
internal static IObservable<int> SqlWrite(string cx, string sql) =>
Observable.Create<int>(o =>
{
using (var conn = new SqlConnection(cx))
{
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
o.OnNext(cmd.ExecuteNonQuery());
}
}
o.OnCompleted();
return Disposable.Empty;
});
答案 0 :(得分:1)
让我们假设您有一个包含当前通知列表的用户界面
public class NotificationListViewModel
{
ObservableCollection<INotification> Items {get;}
}
要维护此集合,您需要了解通知的更改方式。 让我们来展示变化的课程
enum ChangeType
{
Add,
Remove,
Update
}
class Change<T>
{
ChangeType Type {get;}
T Value {get;}
}
现在您可以通过更改公开通知
INotificationProvider
{
public IObservable<Change<INotification>> Notifications {get;}
}
为了方便起见,请在Update
中添加方法INotification
public class NotificationListViewModel
{
public NotificationListViewModel(INotificationProvider provider)
{
provider.Notifications.Subscribe(change =>
{
if(change.Type == ChangeType.Add)
{
Items.Add(change.Value);
}
if(change.Type == ChangeType.Update)
{
Items.First(x => x.Id = change.Value.Id).Update(change.Value);
}
if(change.Type == ChangeType.Remove)
{
Items.Remove(change.Value);
}
});
}
}
要了解收到的更改的类型,您需要维护从数据库读取通知的现有通知列表。
我编写的所有这些代码均显示了“您如何考虑这些事情”的示例。 有一个很棒的库DynamicData,所有这些想法都以便捷且优化的方式实现。