Ayende @ Rahien

It's a girl

Entity Framework: If you pass a connection to the context, you are responsible for disposing it

I recently got a bug report about an issue with EF Prof, apparently the application statistics would record the context being opened, but it wouldn’t show them being closed. The customer was rightfully worried about that, and wanted to know if this is a bug in his code or in EF Prof.

Not closing connections is a pretty bad idea, obviously, because you are going to hold a lot more server resources than you need.

But we couldn’t figure out what the problem was. On my end, I could see that EF Prof was recording the context close properly, but nearly the same code on the customer showed the problem. Note the word nearly. I asked for a repro of the issue, and once I had it, it took mere minutes to confirm that the problem exists.

Now was the time to find out why. The customer code was:

using(var context = new MyContext(new EntityConnection("name=MyConStr"))
{
   // do stuff
}

Now, what EF Prof tells you is a data context open & close are actually more accurately connection open & close. After some extensive study, I verified that it wasn’t my code to blame, there was a leaking connection here.

Checking a bit further, it became clear. We passed an existing connection to the context. When we dispose the context, the context asks: “Am I the owner of this connection?” And since the answer is no, it will not dispose it. It makes sense, you might want to use that connection for your own purposes, and it is pretty rude of the context to close a connection that it doesn’t own.

How can we resolve this? By giving the context the information to open the connection, but not the connection itself:

using(var context = new MyContext("name=MyConStr")
{
   // do stuff
}

This code will instruct the context to open its own connection, which it will know that it owns, so it can safely dispose it when it is disposed.

Look Ma, no leaks!

Tags:

Posted By: Ayende Rahien

Published at

Originally posted at

Comments

Damien Guard
09/25/2010 05:22 PM by
Damien Guard

This applies to LINQ to SQL too - if the connection is a string it will open and close, if it is an existing connection it will not.

[)amien

configurator
09/25/2010 09:15 PM by
configurator

Indeed, classes that accept parameters should not dispose of their parameters; whoever opened the connection should be responsible for closing it.

StreamReader and StreamWriter fail miserably there. Try

using (MemoryStream s = new MemoryStream) {

using (StreamWriter writer = new StreamWriter(s))

writer.write(something);

s.Seek(0);

using (StreamReader reader = new StreamReader(s))

reader.ReadToEnd();

}

Mladen
09/26/2010 01:54 PM by
Mladen

Maybe i'm misunderstanding something here but how is new-ing an EntityConnection using an existing connection?

if you do:

new MyContext(new EntityConnection("name=MyConStr"))

shouldn't that create a new connection in that context?

maybe EF does this differently but i haven't worked with EF yet, so maybe i'm missing something here.

Ayende Rahien
09/26/2010 01:57 PM by
Ayende Rahien

Mladen,

How is EF to know that you didn't pass it from someplace totally different?

Mladen
09/26/2010 02:13 PM by
Mladen

ahhhhhh.... now i got it. If you pass any connection into it! DOH!

Comments have been closed on this topic.