ceth
ceth

Reputation: 45295

Resource management in F#

I know I need to use use keywork to dispose resouce:

use db = new dbml.MobileDataContext(connectionString)
for rows in db.Item do 
....

But I want to create the function which returns db connection:

let getConnection(connectionString) =
   use db = new dbml.MobileDataContext(connectionString)
   db.ExecuteCommand(....) |> ignore
   db

and use this function in my code:

use db = getConnection(connectionString)      
for rows in db.Item do 
....

Do I need to use use-keyword in such case two times: in the function and in the function call ?

Upvotes: 2

Views: 136

Answers (2)

Chad Gilbert
Chad Gilbert

Reputation: 36375

@Tarmil has the right answer but I also wanted to point out a more idiomatic alternative to returning an already-open connection.

You could instead define a withConnection higher order function that takes a function as its parameter. The function you pass in would accept an open connection and return whatever results it wanted, letting withConnection handle the disposal of the connection. Here's the boilerplate:

let withConnection f =
    use db = new dbml.MobileDataContext(connectionString)
    db.ExecuteCommand(....) |> ignore
    f db

You could then use it like this without having to worry about closing the connection from elsewhere in the code:

let users = withConnection (fun conn -> conn.ExecuteQuery(...))

Upvotes: 6

Tarmil
Tarmil

Reputation: 11362

You should only use use in the outer function. If you use it inside getConnection, then your context will be disposed upon returning from getConnection, and so it will be already disposed in the outer function when you want to use it. As a general rule, if you dispose a value in a function then you must not return it.

Upvotes: 6

Related Questions