[英]F# issue with async workflow and try/with
I am having a headache trying to put together a simple functionality. 我正在努力整理一个简单的功能。
Consider the following definitions: 考虑以下定义:
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>
The use Task<T>
because they are libraries developed in other .NET languages. 使用Task<T>
因为它们是用其他.NET语言开发的库。
(I have created this code for the sake of the example) (我为了这个例子创建了这段代码)
Basically, I want to save data in the repository service, and then save the data in the notification service. 基本上,我想在存储库服务中保存数据,然后将数据保存在通知服务中。 But if this second operation fails, and that includes exceptions, I want to rollback the operation in the repository. 但是如果第二个操作失败,并且包含异常,我想回滚存储库中的操作。 Then there are two situations where I would want to call the rollback operation, the first if notification.SaveAsync
returns false, and the second if it throws an exception. 然后有两种情况我想要调用回滚操作,第一种是if notification.SaveAsync
返回false,第二种是它抛出异常。 And of course, I would like to code that call to rollback once, but I cannot find the way. 当然,我想编写一次调用回滚,但我找不到方法。
This is what I have tried: 这是我尝试过的:
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
But unfortunately I get a compiler error on the let! nr = ...
但不幸的是我在let! nr = ...
上遇到了编译器错误let! nr = ...
let! nr = ...
saying: This construct may only be used within computation expressions let! nr = ...
说: 此构造只能在计算表达式中使用
Which would be the right way of doing this? 这是正确的方法吗?
The problem is that when you use let v = e
in computation expressions, the expression e
is an ordinary expression that cannot contain further asynchronous constructs. 问题是当你在计算表达式中使用let v = e
时,表达式e
是一个普通的表达式,不能包含其他异步结构。 That's exactly what happens here: 这正是这里发生的事情:
let notifResult =
try
let! nr = Async.AwaitTask <| notification.SaveAsync(entities)
nr
with _-> false
You can turn this into a nested async
block: 您可以将其转换为嵌套的async
块:
let! notifResult = async {
try
let! nr = Async.AwaitTask <| notification.SaveAsync(entities)
return nr
with _-> return false }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.