After a few years of using Entity Framework in our applications without issue, our company has starting deploying laptops to our users. The laptops are being used on-site, with a direct, wired connection to our network.
Since then, we have seen a huge increase of crashes within our programs, with the exception logs showing
System.Data.SqlClient.SqlException: A transport-level error has occurred when receiving results from the server.
(provider: Session Provider, error: 19 - Physical connection is not usable)
My theory is that the issue stems from the fact that the laptops, unlike the PCs, go to sleep. I think that the network adapter is being disabled when the laptop goes to sleep, and re-enabled when it wakes back up. I think our programs are still trying to communicate with the server using a connection that is no longer there.
So, my idea was to respond to:
Microsoft.Win32.SystemEvents.PowerModeChanged
I can detect when it wakes up and refresh the connection. The trouble is that the only way that I can seem to do this is to dispose of the current DbContext and instantiate a new one.
The problem with this is that any uncommitted changes are then lost. If the user has been working all day on updating a record, they would lose their work. Not only that, but we would have to go through all of our applications, and all of our viewmodels and incorporate some sort of kick out of edit mode with notifications to the user. Not pretty at all.
A second idea I've had was to create a method to clone a DbContext . When the computer wakes up, I could create a new DbContext and copy the state from the old one before disposing of it... but some of our data models are massive, and creating a deep clone method for each would be quite the undertaking.
It occurs to me that this might still be the way we have to go... but I'd be stupid not to check if anyone knows of a way to refresh the connection of an Entity Framework DbContext without losing it's current state.
I would appreciate any advice that anyone might have.
I'm not sure, whether it will help in your specific case, but you can check the status of the connection used by your DbConetxt
class and eventually reopen it.
if(context.Database.Connection.State == ConnectionState.Closed) {
context.Database.Connection.Open();
}
it it also possible to pass a connection to the DbContext
in it's constructor and manage this connection manually.
var conn = new SqlConnection("{connectionString}"));
var context = new DbContext(conn, contextOwnsConnection: false);
...
if(conn.State == ConnectionState.Closed) {
conn.Open();
}
context.SaveChanges();
...
context.Dispose();
conn.Dispose();
There are some limitations, if you want to use this code in the EF 5 or earlier versios. See official documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With