Reputation: 2416
I need to use application rule security on sql server. And i want to use Enity Framework Code First.
After a successful login my connection is set to application role. I then create my DbContext using this connection.
But: EF expects a closed connection object. And closing a connection drops the application role.
How can i solve this dilemma?
Upvotes: 3
Views: 2430
Reputation: 1014
Since this question is high on the search result list, I just wanted to throw in a word of caution. I have an app that needed to use an application role and okrumnow's solution seemed at first to work.
However, in unit testing I discovered that sometimes handling the StateChanged event will cause the event to be raised twice and you'll get the error:
"Impersonate Session Security Context" cannot be called in this batch because a simultaneous batch has called it.
It seems to help to change the conditional to:
args.CurrentState == ConnectionState.Open &&
args.CurrentState == ConnectionState.Closed
But it still doesn't eliminate the error. I confirmed this in EF4.3 and EF5. Ladislav is correct that the ideal way is creating a connection for the DbContext and telling the context that it doesn't own it.
Also, connection pooling is never possible with this setup since there is no ConnectionState.Closing
event where you can call sp_unsetapprole
before your connection is closed.
Since I had the flexibility, my solution was to eliminate the usage of an app role and using a dedicated SQL login instead. Either way you're hard-coding a password...
Upvotes: 4
Reputation: 2416
I managed to get this work with two steps:
Switch connection pooling off, which is mentioned all the time for connections using application roles. As i have a desktop application, this is no problem for me.
Add a handler to DbConnection.StateChanged
and activate the application role on every opening of the connection. Without connection pooling, it is not necessary to sp_unsetapprole
on closing. So this works for me:
context.Database.Connection.StateChanged += (sender, args) =>
if (args.CurrentState == ConnectionState.Open) {
activateAppRole((DbConnection)sender, ...);
}
}
I guess, if Pooling is vital for someone, she may call sp_unsetapprole
on closing the connection in this same handler.
Upvotes: 6
Reputation: 364369
EF doesn't have any native support for this. I guess the workaround can be:
Upvotes: 0