@@ -44,12 +44,46 @@ public void DropAssociatedLogins()
4444 {
4545 var logins = Users . Where ( u => u . Login != null && u . Login . Name != "sa" )
4646 . Select ( u => u . Login . Properties ( ) ) ;
47- foreach ( var login in logins )
48- _server . DropLogin ( new LoginProperties {
47+ foreach ( var login in logins )
48+ _server . DropLogin ( new LoginProperties
49+ {
4950 Name = login . Name
5051 } ) ;
5152 }
5253
54+ public User AddUser ( UserProperties userProperties )
55+ {
56+ var user = Users . SingleOrDefault ( u => u . Name . Equals ( userProperties . Name , StringComparison . InvariantCultureIgnoreCase ) ) ;
57+ if ( user == null )
58+ {
59+ var smoUser = new Microsoft . SqlServer . Management . Smo . User ( _database , userProperties . Name )
60+ { Login = userProperties . LoginName } ;
61+ smoUser . Create ( ) ;
62+ user = new User ( smoUser , _server ) ;
63+
64+ foreach ( var role in userProperties . Roles )
65+ {
66+ user . AddRole ( role ) ;
67+ }
68+
69+ GrantPermission ( userProperties ) ;
70+ }
71+
72+ return user ;
73+ }
74+
75+ private void GrantPermission ( UserProperties userProperties )
76+ {
77+ _database . Grant ( userProperties . Permissions , userProperties . Name ) ;
78+ }
79+
80+ public void DropUser ( UserProperties userProperties )
81+ {
82+ var matchingUser =
83+ Users . SingleOrDefault ( u => u . Name . Equals ( userProperties . Name , StringComparison . InvariantCultureIgnoreCase ) ) ;
84+ matchingUser ? . Drop ( ) ;
85+ }
86+
5387 /// <summary>
5488 /// Kills connections and deletes the database.
5589 /// </summary>
@@ -61,7 +95,8 @@ public void Drop()
6195 . Handle < FailedOperationException > ( )
6296 . WaitAndRetry ( 3 , retryAttempt => TimeSpan . FromMilliseconds ( Math . Pow ( 10 , retryAttempt ) ) ) ;
6397
64- policy . Execute ( ( ) => {
98+ policy . Execute ( ( ) =>
99+ {
65100 _database . Refresh ( ) ;
66101 _database . Parent . KillDatabase ( _database . Name ) ;
67102 } ) ;
@@ -97,8 +132,9 @@ public List<BackupMetadata> MostRecentBackupChain()
97132 cmd . Parameters . Add ( dbName ) ;
98133
99134 using var reader = cmd . ExecuteReader ( ) ;
100- while ( reader . Read ( ) )
101- backups . Add ( new BackupMetadata {
135+ while ( reader . Read ( ) )
136+ backups . Add ( new BackupMetadata
137+ {
102138 CheckpointLsn = ( decimal ) reader [ "checkpoint_lsn" ] ,
103139 DatabaseBackupLsn = ( decimal ) reader [ "database_backup_lsn" ] ,
104140 DatabaseName = ( string ) reader [ "database_name" ] ,
@@ -129,7 +165,7 @@ public decimal MostRecentFullBackupLsn()
129165 cmd . Parameters . Add ( dbName ) ;
130166
131167 using var reader = cmd . ExecuteReader ( ) ;
132- if ( ! reader . Read ( ) )
168+ if ( ! reader . Read ( ) )
133169 throw new Exception ( "MostRecentFullBackup SQL found no results" ) ;
134170
135171 var lsnValue = reader [ "most_recent_full_backup_checkpoint_lsn" ] ;
@@ -166,8 +202,9 @@ public List<BackupMetadata> BackupChainFromLsn(decimal checkpointLsn)
166202 cmd . Parameters . Add ( lsnParam ) ;
167203
168204 using var reader = cmd . ExecuteReader ( ) ;
169- while ( reader . Read ( ) )
170- backups . Add ( new BackupMetadata {
205+ while ( reader . Read ( ) )
206+ backups . Add ( new BackupMetadata
207+ {
171208 CheckpointLsn = ( decimal ) reader [ "checkpoint_lsn" ] ,
172209 DatabaseBackupLsn = ( decimal ) reader [ "database_backup_lsn" ] ,
173210 DatabaseName = ( string ) reader [ "database_name" ] ,
@@ -210,23 +247,26 @@ private void ThrowIfUnreadyToDrop()
210247 . WaitAndRetry ( 6 , retryAttempt => TimeSpan . FromMilliseconds ( Math . Pow ( 5 , retryAttempt ) ) ) ;
211248
212249 // ensure database is not in AvailabilityGroup, WaitAndRetry loop for each instance to sync
213- policyPrep . Execute ( ( ) => {
250+ policyPrep . Execute ( ( ) =>
251+ {
214252 _database . Refresh ( ) ;
215- if ( Restoring )
253+ if ( Restoring )
216254 return ; // restoring state means we're good to drop
217255
218- try {
219- if ( ! string . IsNullOrEmpty ( _database . AvailabilityGroupName ) )
256+ try
257+ {
258+ if ( ! string . IsNullOrEmpty ( _database . AvailabilityGroupName ) )
220259 throw
221260 new Exception ( $ "Cannot kill the database { Name } until it has been removed from the AvailabilityGroup") ;
222- if ( _database . AvailabilityDatabaseSynchronizationState >
261+ if ( _database . AvailabilityDatabaseSynchronizationState >
223262 AvailabilityDatabaseSynchronizationState . NotSynchronizing )
224263 throw new
225264 Exception ( $ "Cannot kill the database { Name } until AvailabilityDatabaseSynchronizationState is inaccessible") ;
226265 }
227- catch (
228- PropertyCannotBeRetrievedException ) { } // good here, AvailabilityDatabaseSynchronizationState unavailable means it has no state
229- catch ( SmoException e ) when ( e . Message . Contains ( "Cannot access properties or methods" ) ) { }
266+ catch (
267+ PropertyCannotBeRetrievedException )
268+ { } // good here, AvailabilityDatabaseSynchronizationState unavailable means it has no state
269+ catch ( SmoException e ) when ( e . Message . Contains ( "Cannot access properties or methods" ) ) { }
230270 } ) ;
231271 }
232272 }
0 commit comments