Please bear with me if this seems like its off topic due to some part of the sample being ADO.Net. I believe the problem is in the Database engine since all clients fail. It seems like after a contained authenticated user is created, existing connections fail to re-login, such as from a connection pool.
Here is a complete example:
Creating a contained user in my SQL Server Express 2014 partially contained database, causes exception when performing queries on existing open connections.
Here is the SQL to turn on contained DB authentication and create the database:
EXEC sp_configure 'contained database authentication',1RECONFIGURE
GOCREATEDATABASE TestContainedUserAuth CONTAINMENT = PARTIAL;
GOUSE TestContainedUserAuth;
GOCREATEUSER TestCreatorUser WITH PASSWORD='Test1234';
GOALTER ROLE db_owner ADD MEMBER TestCreatorUser;
GOCREATETABLE[dbo].[TestTable]([TestTableID][int]NOTNULL)ON[PRIMARY]
GO
Here is the .Net 4.6.1 code for performing the query (please create a console project and paste this in Program.cs, and of course change server and instance name to match yours):
using System.Data.SqlClient;
namespace ConsoleApplication
{
class Program{
static void Main(string[] args){while(true){using(var connection = new SqlConnection("Integrated Security=False;Data Source=localhost\\SQLEXPRESS;Initial Catalog=TestContainedUserAuth;User ID=TestCreatorUser;Password=Test1234")){
connection.Open();using(var cmd = new SqlCommand(@"SELECT * FROM TestTable", connection)){
cmd.ExecuteNonQuery();}}}}}}
Now, after running the C# program to perform this query in a loop, run this from SQL Management Studio (BTW, we are fully aware of the security risks associated with contained databases and with dbo users in a contained database):
IFEXISTS(SELECT*FROM sys.database_principals WHERE name = N'MyNewUser')DROPUSER MyNewUser;
GOCREATEUSER MyNewUser WITH PASSWORD=N'Abcd1234';
GO
After executing CREATE USER MyNewUser
(which executes successfully) in SQL Management Studio, I'm getting this exception in the C# program:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Login failed for user 'S-1-9-3-1497860641-1239606672-4234875017-3655542527'.
A severe error occurred on the current command. The results, if any, should be discarded.
If I modify the code to keep a reference to the connection and not open and close the connection for each query I don't get the exception. So it appears as though the exception is happening when ExecuteNonQuery attempts to re-login on the connection after the connection is obtained from the pool, but I'm not sure.
Additionally if pooling is turned off (Pooling=False
in the connection string), the exception doesn't occur.
Finally, after this error occurs once on one connection, it seems like existing pooled connections are "healed" and queries executed on existing connections are successful from then on, until another 'CREATE USER' is performed.
Neither keeping a reference to a permanently open connection or turning off pooling is a practical solution to this error. Any help would be appreciated.