我正在努力整理一个简单的功能。
考虑以下定义:
type Entity = {Id:int;Data:string}
type IRepository =
abstract member SaveAsync: array<Entity> -> Task<bool>
abstract member RollBackAsync: array<Entity> -> Task<bool>
type INotification =
abstract member SaveAsync: array<Entity> -> Task<bool>
使用Task<T>
因为它们是用其他.NET语言开发的库。
(我为了这个例子创建了这段代码)
基本上,我想在存储库服务中保存数据,然后将数据保存在通知服务中。但是如果第二个操作失败,并且包含异常,我想回滚存储库中的操作。然后我有两种情况需要调用回滚操作,第一个if notification.SaveAsync
返回false,第二个if抛出异常。当然,我想编写一次调用回滚,但我找不到方法。
这就是我的尝试:
type Controller(repository:IRepository, notification:INotification) =
let saveEntities entities:Async<bool> = async{
let! repoResult = Async.AwaitTask <| repository.SaveAsync(entities)
if(not repoResult) then
return false
else
let notifResult =
try
let! nr = Async.AwaitTask <| notification.SaveAsync(entities)
nr
with
| _-> false
if(not notifResult) then
let forget = Async.AwaitTask <| repository.RollBackAsync(entities)
return false
else
return true
}
member self.SaveEntitiesAsync(entities:array<Entity>) =
Async.StartAsTask <| saveEntities entities
但遗憾的是我在let! nr = ...
上遇到编译错误:此构造只能在计算表达式中使用
这是正确的做法吗?
答案 0 :(得分:9)
问题在于,当您在计算表达式中使用let v = e
时,表达式e
是一个普通表达式,不能包含其他异步结构。这就是这里发生的事情:
let notifResult =
try
let! nr = Async.AwaitTask <| notification.SaveAsync(entities)
nr
with _-> false
您可以将其转换为嵌套的async
块:
let! notifResult = async {
try
let! nr = Async.AwaitTask <| notification.SaveAsync(entities)
return nr
with _-> return false }