1
\$\begingroup\$

How to flatten the nested try-catch block in F# for the following code? I am using EF Core with F#. The nested is required because I need to Rollback the transaction if there are errors in saving or committing the transaction!

let createTenant (ctx: AppContext) (tenant: Db.Tenant) (firstUser: Db.User) =
    async {
        try
            let! db = ctx.Aquire()
            
            use! transaction = db.Database.BeginTransactionAsync(IsolationLevel.Serializable) |> Async.AwaitTask

            db.Tenant.Add tenant |> ignore
            db.User.Add firstUser |> ignore

            let! result =
                async {
                    try
                        let! _ = db.SaveChangesAsync() |> Async.AwaitTask
                        do! transaction.CommitAsync() |> Async.AwaitTask
                        
                        return Ok tenant.Id
                    with
                    | _ ->
                        do! transaction.RollbackAsync() |> Async.AwaitTask
                        return Error "internal error"
                }

            ctx.Release()

            return result

        with
        | _ -> return Error "internal error"
    }

On a side note, is this the clean/idiomatic way to handle exceptions in F#? Is there a better way to do this?

\$\endgroup\$
6
  • \$\begingroup\$ The current question title of your question is too generic to be helpful. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How do I ask a good question?. \$\endgroup\$ – BCdotWEB Sep 27 '20 at 18:36
  • \$\begingroup\$ You don't need the inner try/catch. If SaveChangesAsync() errors then the transaction will be rolled back anyway and you jump into the outer try/catch. \$\endgroup\$ – Gert Arnold Sep 29 '20 at 6:38
  • \$\begingroup\$ @GertArnold I am new to EF Core. Does it automatically rollback the transaction if there are errors in SaveChangesAsync() or CommitAsync() method? \$\endgroup\$ – Harshal Patil Sep 29 '20 at 7:34
  • 1
    \$\begingroup\$ Yep. It's all or nothing with these methods. \$\endgroup\$ – Gert Arnold Sep 29 '20 at 7:38
  • 1
    \$\begingroup\$ Not related to question, but since you're working mostly with TPL and Task class, it would be better to use Ply or TaskBuilder to avoid usage of Async.AwaitTask which might be slow and gives better interop experience when your library is called from other languages \$\endgroup\$ – JL0PD Mar 12 at 5:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.