I have a database connection with a query similar to as follows in a couple separate files in a project:
SqlTypes.fs
module SqlTypes
open FSharp.Data.TypeProviders
type DBType = SqlDataConnection<ConnectionStrings.DbConnStr>
let getDb() = DBType.GetDataContext() //will this cause a memory leak when called from outside here?
Utilities.fs
module Utilities
open System
open SqlTypes
open System.Linq
///Returns an IQueryable of Orders whose OrderStatus is less than 5 (Not yet released)
let private getOrdersNotYetReleased () =
let orders = query {
for order in getDb().Orders do //memleak here?
where(order.Status < 5)
sortBy (order.CreatedDateUtc)
select order
}
//return
orders
Q: Is it necessary to use a use
clause (like in the following) to prevent a memory leak?
///Returns an IQueryable of Orders whose OrderStatus is less than 5 (Not yet released)
let private getOrdersNotYetReleased () =
use db = DBType.GetDataContext() //is this safer? Does it matter if this `use` is here?
let orders = query {
for order in db.Orders do
where(order.Status < 5)
sortBy (order.CreatedDateUtc)
select order
}
//return
orders
Or, will Dispose()
be called on the Db object when the computation block exits?
The IDisposable
pattern provides for a Dispose()
method. The use
keyword is there to take advantage of this pattern; if a class implements IDisposable
, the author of the class is telling you that using the use
keyword with their class is probably a good idea.
What the Dispose()
method actually does depends entirely on what code the author of the class writes for the Dispose()
method. There is no guarantee that it even does anything.
Microsoft's official word on IDisposable
has always been that its purpose is to "clean up unmanaged resources," but in practice, Dispose()
does whatever the author of the class believes it needs to do to gracefully shut down the object. What it generally does not do is recover memory from managed objects; that is the purpose of the garbage collector.
But, generally speaking, if a class implements IDisposable
, that means it contains a Dispose()
method that does something meaningful for the disposition of the object, like closing files or database connections, for example. So. Class implements IDisposable
? Use use
with it.
Further Reading
Managing Resources in F#