From 7efef4e6dbeeacdcba3e3e33f0425f648aa3e1b5 Mon Sep 17 00:00:00 2001 From: Gilles TOURREAU Date: Tue, 20 Aug 2024 12:39:47 +0200 Subject: [PATCH] Fix the initializer with DbContext to use admin rights. --- .../SqlServerDatabaseInitializer.cs | 19 ++++++-- ...tabaseInitializerDbContextWithLoginTest.cs | 44 ++++++++++++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/UnitTests.Databases.SqlServer/SqlServerDatabaseInitializer.cs b/src/UnitTests.Databases.SqlServer/SqlServerDatabaseInitializer.cs index 27b4a6f..cbb3b40 100644 --- a/src/UnitTests.Databases.SqlServer/SqlServerDatabaseInitializer.cs +++ b/src/UnitTests.Databases.SqlServer/SqlServerDatabaseInitializer.cs @@ -47,21 +47,32 @@ IF SUSER_ID ('{connectionStringBuilder.UserID}') IS NULL public SqlServerDatabase Initialize(TContext context) where TContext : DbContext { - var connectionStringBuilder = new SqlConnectionStringBuilder(context.Database.GetDbConnection().ConnectionString); + var connectionString = context.Database.GetConnectionString(); - var server = new SqlServer(context.Database.GetDbConnection().ConnectionString); + var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString); + + var server = new SqlServer(connectionString!); + var database = server.GetDatabase(connectionStringBuilder.InitialCatalog); if (!this.isDeployed) { server.DeleteDatabase(connectionStringBuilder.InitialCatalog); + // Change the connection with administrator rights. + context.Database.SetConnectionString(database.AsAdministrator().ConnectionString); context.Database.EnsureCreated(); + context.Database.SetConnectionString(connectionString); + + if (!string.IsNullOrWhiteSpace(connectionStringBuilder.UserID)) + { + server.Master.ExecuteNonQuery($@" + IF SUSER_ID ('{connectionStringBuilder.UserID}') IS NULL + CREATE LOGIN [{connectionStringBuilder.UserID}] WITH PASSWORD = '{connectionStringBuilder.Password}'"); + } this.isDeployed = true; } - var database = server.GetDatabase(connectionStringBuilder.InitialCatalog); - ClearAllData(database.AsAdministrator()); return database; diff --git a/tests/UnitTests.Databases.SqlServer.Tests/SqlServerDatabaseInitializerDbContextWithLoginTest.cs b/tests/UnitTests.Databases.SqlServer.Tests/SqlServerDatabaseInitializerDbContextWithLoginTest.cs index d9f7bb3..e377820 100644 --- a/tests/UnitTests.Databases.SqlServer.Tests/SqlServerDatabaseInitializerDbContextWithLoginTest.cs +++ b/tests/UnitTests.Databases.SqlServer.Tests/SqlServerDatabaseInitializerDbContextWithLoginTest.cs @@ -6,6 +6,8 @@ namespace PosInformatique.UnitTests.Databases.SqlServer.Tests { + using Microsoft.EntityFrameworkCore; + [Collection("PosInformatique.UnitTests.Databases.SqlServer.Tests")] public class SqlServerDatabaseInitializerDbContextWithLoginTest : IClassFixture { @@ -15,7 +17,16 @@ public class SqlServerDatabaseInitializerDbContextWithLoginTest : IClassFixture< public SqlServerDatabaseInitializerDbContextWithLoginTest(SqlServerDatabaseInitializer initializer) { - this.database = initializer.Initialize("UnitTests.Databases.SqlServer.Tests.DacPac.dacpac", ConnectionString); + var optionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer(ConnectionString); + + using var context = new DbContextTest(optionsBuilder.Options); + + this.database = initializer.Initialize(context); + + this.database.AsAdministrator().ExecuteNonQuery("IF NOT EXISTS (SELECT 1 FROM [sys].[sysusers] WHERE name = 'ServiceAccountUser') CREATE USER [ServiceAccountUser] FOR LOGIN [ServiceAccountLogin]"); + this.database.AsAdministrator().ExecuteNonQuery("GRANT CONNECT TO [ServiceAccountUser]"); + this.database.AsAdministrator().ExecuteNonQuery("GRANT SELECT, INSERT ON [MyTable] TO [ServiceAccountUser]"); var table = this.database.ExecuteQuery("SELECT * FROM MyTable"); @@ -66,5 +77,36 @@ public void Test2() // Insert a row which should not be use in other tests. this.database.InsertInto("MyTable", new { Id = 99, Name = "Should not be here for the next unit test" }); } + + private sealed class DbContextTest : DbContext + { + public DbContextTest(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(t => + { + t.ToTable("MyTable"); + + t.Property(t => t.Id) + .ValueGeneratedNever(); + + t.Property(t => t.Name) + .IsRequired() + .HasMaxLength(50) + .IsUnicode(false); + }); + } + } + + private sealed class Table + { + public int Id { get; set; } + + public string Name { get; set; } + } } } \ No newline at end of file