diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f123e70475..94d2d514e8 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,35 +1,2 @@ -# AI Instructions - -This file provides AI agent guidance for the project. Each instruction file below -targets specific file glob patterns and use cases. - -## Build & Test Workflow -- Run in PowerShell, from repository root -- Build before running tests: `.\build.ps1 -Tasks build` -- Always run tests in new PowerShell session: `Invoke-Pester -Path @({test paths}) -Output Detailed` - -## Instructions Overview - -The guidelines always take priority over existing code patterns in project. - +# Requirements - SqlServerDsc-specific guidelines override general project guidelines -- Follow PowerShell style guidelines -- Maintain localization requirements across all source files -- Follow test patterns strictly for maintainability - -## Core Project Guidelines - -- Follow SqlServerDsc project specific guidelines: [./instructions/SqlServerDsc-guidelines.instructions.md](./instructions/SqlServerDsc-guidelines.instructions.md) -- Always follow PowerShell code style guidelines: [./instructions/dsc-community-style-guidelines-powershell.instructions.md](./instructions/dsc-community-style-guidelines-powershell.instructions.md) -- Follow Project-level guidelines: [./instructions/dsc-community-style-guidelines.instructions.md](./instructions/dsc-community-style-guidelines.instructions.md) -- Follow localization requirements: [./instructions/dsc-community-style-guidelines-localization.instructions.md](./instructions/dsc-community-style-guidelines-localization.instructions.md) -- Always add Unit testing according to: [./instructions/dsc-community-style-guidelines-unit-tests.instructions.md](./instructions/dsc-community-style-guidelines-unit-tests.instructions.md) -- Always add Integration testing according to: [./instructions/dsc-community-style-guidelines-integration-tests.instructions.md](./instructions/dsc-community-style-guidelines-integration-tests.instructions.md) -- Follow Markdown formatting requirements: [./instructions/dsc-community-style-guidelines-markdown.instructions.md](./instructions/dsc-community-style-guidelines-markdown.instructions.md) -- Always update CHANGELOG.md: [./instructions/dsc-community-style-guidelines-changelog.instructions.md](./instructions/dsc-community-style-guidelines-changelog.instructions.md) - -## Desired State Configuration (DSC) Resource Guidelines - -New DSC resources should always be created as class-based resources. - -- Follow class-based resources guidelines: [./instructions/dsc-community-style-guidelines-class-resource.instructions.md](./instructions/dsc-community-style-guidelines-class-resource.instructions.md) diff --git a/.github/instructions/dsc-community-style-guidelines-class-resource.instructions.md b/.github/instructions/dsc-community-style-guidelines-class-resource.instructions.md index abd5a3766a..c7f35f0c01 100644 --- a/.github/instructions/dsc-community-style-guidelines-class-resource.instructions.md +++ b/.github/instructions/dsc-community-style-guidelines-class-resource.instructions.md @@ -86,9 +86,9 @@ Add to .DESCRIPTION section: - `## Requirements`: List minimum requirements - `## Known issues`: Critical issues + pattern: `All issues are not listed here, see [all open issues](https://github.com/{owner}/{repo}/issues?q=is%3Aissue+is%3Aopen+in%3Atitle+{ResourceName}).` -## Error Handling +## Error Handling for classes - Use `try/catch` blocks to handle exceptions -- Do not use `throw` for terminating errors, use `New-*Exception` commands: +- Do not use `throw` for terminating errors, use `New-*Exception` commands (never for functions): - [`New‑InvalidDataException`](https://github.com/dsccommunity/DscResource.Common/wiki/New%E2%80%91InvalidDataException) - [`New-ArgumentException`](https://github.com/dsccommunity/DscResource.Common/wiki/New%E2%80%91ArgumentException) - [`New-InvalidOperationException`](https://github.com/dsccommunity/DscResource.Common/wiki/New%E2%80%91InvalidOperationException) diff --git a/.github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md b/.github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md index ce0703937d..e0861e9d92 100644 --- a/.github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md +++ b/.github/instructions/dsc-community-style-guidelines-mof-resources.instructions.md @@ -28,10 +28,9 @@ applyTo: "source/DSCResources/**/*.psm1" - Use localized strings for all messages (Write-Verbose, Write-Error, etc.) - Import localized strings using `Get-LocalizedData` at module top -## Error Handling -- Do not use `throw` for terminating errors +## Error Handling for MOF-based resources - Use `try/catch` blocks to handle exceptions -- Throw localized exceptions using the appropriate `New-*Exception` cmdlet: +- Do not use `throw` for terminating errors, use `New-*Exception` commands (never for functions): - [`New‑InvalidDataException`](https://github.com/dsccommunity/DscResource.Common/wiki/New%E2%80%91InvalidDataException) - [`New-ArgumentException`](https://github.com/dsccommunity/DscResource.Common/wiki/New%E2%80%91ArgumentException) - [`New-InvalidOperationException`](https://github.com/dsccommunity/DscResource.Common/wiki/New%E2%80%91InvalidOperationException) diff --git a/.github/instructions/dsc-community-style-guidelines-powershell.instructions.md b/.github/instructions/dsc-community-style-guidelines-powershell.instructions.md index cbf29be452..b2f7f13222 100644 --- a/.github/instructions/dsc-community-style-guidelines-powershell.instructions.md +++ b/.github/instructions/dsc-community-style-guidelines-powershell.instructions.md @@ -79,6 +79,7 @@ applyTo: "**/*.ps?(m|d)1" - For state-changing functions, use `SupportsShouldProcess` - Place ShouldProcess check immediately before each state-change - `$PSCmdlet.ShouldProcess` must use required pattern + - Inside `$PSCmdlet.ShouldProcess`-block, avoid using `Write-Verbose` - Never use backtick as line continuation in production code. - Set `$ErrorActionPreference = 'Stop'` before commands using `-ErrorAction 'Stop'`; restore after @@ -89,7 +90,7 @@ applyTo: "**/*.ps?(m|d)1" - Use `Write-Verbose` for: High-level execution flow only; User-actionable information - Use `Write-Information` for: User-facing status updates; Important operational messages; Non-error state changes - Use `Write-Warning` for: Non-fatal issues requiring attention; Deprecated functionality usage; Configuration problems that don't block execution -- Use `$PSCmdlet.ThrowTerminatingError()` for terminating errors (except for classes), use relevant error category +- Use `$PSCmdlet.ThrowTerminatingError()` for terminating errors (except for classes), use relevant error category, in try-catch include exception - Use `Write-Error` for non-terminating errors, use relevant error category ## ShouldProcess Required Pattern diff --git a/.github/instructions/dsc-community-style-guidelines.instructions.md b/.github/instructions/dsc-community-style-guidelines.instructions.md index ccc3bb3fe9..1db020e9d5 100644 --- a/.github/instructions/dsc-community-style-guidelines.instructions.md +++ b/.github/instructions/dsc-community-style-guidelines.instructions.md @@ -22,10 +22,12 @@ applyTo: "**" - Integration tests: `tests/Integration/Commands/{CommandName}.Integration.Tests.ps1` ## Requirements -- Follow guidelines over existing code patterns +- Follow instructions over existing code patterns +- Follow PowerShell style and test guideline instructions strictly - Always update CHANGELOG.md Unreleased section - Localize all strings using string keys; remove any orphaned string keys - Check DscResource.Common before creating private functions - Separate reusable logic into private functions +- DSC resources should always be created as class-based resources - Add unit tests for all commands/functions/resources - Add integration tests for all public commands and resources diff --git a/.vscode/settings.json b/.vscode/settings.json index 17c15a6e1f..e47a41bedc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -90,7 +90,8 @@ "SOURCEBRANCH", "SOURCEBRANCHNAME", "setvariable", - "RAISERROR" + "RAISERROR", + "filegroup" ], "cSpell.ignorePaths": [ ".git" diff --git a/CHANGELOG.md b/CHANGELOG.md index ae57f26f19..184f61aa19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added setup workflow for GitHub Copilot. - Switch the workflow to use Linux. - - Attempt to unshallow the Copilot branch +- `Set-SqlDscDatabaseDefault` + - Added new command to set default objects of a database in a SQL Server + Database Engine instance (issue [#2178](https://github.com/dsccommunity/SqlServerDsc/issues/2178)). + - The command can set the default filegroup, default FILESTREAM filegroup, + and default Full-Text catalog using SMO methods SetDefaultFileGroup, + SetDefaultFileStreamFileGroup, and SetDefaultFullTextCatalog. - `SqlAgentAlert` - Added new DSC resource to manage SQL Server Agent alerts. - Improved AI instructions. @@ -82,7 +87,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Set-SqlDscDatabase` - Modify properties of an existing database - `Remove-SqlDscDatabase` - Remove a database from SQL Server instance - `Test-SqlDscDatabase` - Test if a database is in the desired state - - All commands support pipeline input with ServerObject and follow established patterns + - All commands support pipeline input with ServerObject and follow established + patterns - Database objects can also be used as pipeline input for Set and Remove operations - Commands include comprehensive validation, localization, and ShouldProcess support diff --git a/source/Public/Set-SqlDscDatabaseDefault.ps1 b/source/Public/Set-SqlDscDatabaseDefault.ps1 new file mode 100644 index 0000000000..3bd898a2b6 --- /dev/null +++ b/source/Public/Set-SqlDscDatabaseDefault.ps1 @@ -0,0 +1,213 @@ +<# + .SYNOPSIS + Sets default objects of a database in a SQL Server Database Engine instance. + + .DESCRIPTION + This command sets default objects of a database in a SQL Server Database Engine instance. + It can set the default filegroup, default FILESTREAM filegroup, and default Full-Text catalog + using SMO methods. + + .PARAMETER ServerObject + Specifies current server connection object. + + .PARAMETER DatabaseObject + Specifies a database object to modify. + + .PARAMETER Name + Specifies the name of the database to be modified. + + .PARAMETER DefaultFileGroup + Sets the default filegroup for the database. The filegroup must exist in the database. + + .PARAMETER DefaultFileStreamFileGroup + Sets the default FILESTREAM filegroup for the database. The filegroup must exist in the database. + + .PARAMETER DefaultFullTextCatalog + Sets the default Full-Text catalog for the database. The catalog must exist in the database. + + .PARAMETER Force + Specifies that the database defaults should be modified without any confirmation. + + .PARAMETER Refresh + Specifies that the **ServerObject**'s databases should be refreshed before + modifying the database object. This is helpful when databases could have been + modified outside of the **ServerObject**, for example through T-SQL. But + on instances with a large amount of databases it might be better to make + sure the **ServerObject** is recent enough, or pass in **DatabaseObject**. + + .PARAMETER PassThru + Specifies that the database object should be returned after modification. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $databaseObject = $serverObject | Get-SqlDscDatabase -Name 'MyDatabase' + $databaseObject | Set-SqlDscDatabaseDefault -DefaultFileGroup 'MyFileGroup' + + Sets the default filegroup of the database named **MyDatabase** to **MyFileGroup**. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Set-SqlDscDatabaseDefault -Name 'MyDatabase' -DefaultFullTextCatalog 'MyCatalog' -Force + + Sets the default Full-Text catalog of the database named **MyDatabase** to **MyCatalog** without prompting for confirmation. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $databaseObject = $serverObject | Get-SqlDscDatabase -Name 'MyDatabase' + $databaseObject | Set-SqlDscDatabaseDefault -DefaultFileGroup 'DataFileGroup' -DefaultFileStreamFileGroup 'FileStreamFileGroup' -DefaultFullTextCatalog 'FTCatalog' + + Sets multiple default objects for the database named **MyDatabase**. + + .INPUTS + Microsoft.SqlServer.Management.Smo.Server + Server object accepted from the pipeline (ServerObject parameter set). + + Microsoft.SqlServer.Management.Smo.Database + Database object accepted from the pipeline (DatabaseObject parameter set). + + .OUTPUTS + None. But when **PassThru** is specified the output is `[Microsoft.SqlServer.Management.Smo.Database]`. +#> +function Set-SqlDscDatabaseDefault +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType([Microsoft.SqlServer.Management.Smo.Database])] + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] + param + ( + [Parameter(ParameterSetName = 'ServerObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Server] + $ServerObject, + + [Parameter(ParameterSetName = 'DatabaseObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Database] + $DatabaseObject, + + [Parameter(ParameterSetName = 'ServerObject', Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $DefaultFileGroup, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $DefaultFileStreamFileGroup, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $DefaultFullTextCatalog, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force, + + [Parameter(ParameterSetName = 'ServerObject')] + [System.Management.Automation.SwitchParameter] + $Refresh, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru + ) + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ServerObject') + { + # Get the database object + $previousErrorActionPreference = $ErrorActionPreference + $ErrorActionPreference = 'Stop' + + $DatabaseObject = $ServerObject | Get-SqlDscDatabase -Name $Name -Refresh:$Refresh.IsPresent -ErrorAction 'Stop' + + $ErrorActionPreference = $previousErrorActionPreference + } + else + { + $Name = $DatabaseObject.Name + $ServerObject = $DatabaseObject.Parent + } + + Write-Verbose -Message ($script:localizedData.DatabaseDefault_Set -f $Name, $ServerObject.InstanceName) + + if ($Force.IsPresent -and -not $Confirm) + { + $ConfirmPreference = 'None' + } + + try + { + $wasUpdate = $false + + if ($PSBoundParameters.ContainsKey('DefaultFileGroup')) + { + $descriptionMessage = $script:localizedData.DatabaseDefault_SetFileGroup_ShouldProcessVerboseDescription -f $Name, $DefaultFileGroup, $ServerObject.InstanceName + $confirmationMessage = $script:localizedData.DatabaseDefault_SetFileGroup_ShouldProcessVerboseWarning -f $Name, $DefaultFileGroup + $captionMessage = $script:localizedData.DatabaseDefault_SetFileGroup_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage)) + { + $DatabaseObject.SetDefaultFileGroup($DefaultFileGroup) + $wasUpdate = $true + } + } + + if ($PSBoundParameters.ContainsKey('DefaultFileStreamFileGroup')) + { + $descriptionMessage = $script:localizedData.DatabaseDefault_SetFileStreamFileGroup_ShouldProcessVerboseDescription -f $Name, $DefaultFileStreamFileGroup, $ServerObject.InstanceName + $confirmationMessage = $script:localizedData.DatabaseDefault_SetFileStreamFileGroup_ShouldProcessVerboseWarning -f $Name, $DefaultFileStreamFileGroup + $captionMessage = $script:localizedData.DatabaseDefault_SetFileStreamFileGroup_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage)) + { + $DatabaseObject.SetDefaultFileStreamFileGroup($DefaultFileStreamFileGroup) + $wasUpdate = $true + } + } + + if ($PSBoundParameters.ContainsKey('DefaultFullTextCatalog')) + { + $descriptionMessage = $script:localizedData.DatabaseDefault_SetFullTextCatalog_ShouldProcessVerboseDescription -f $Name, $DefaultFullTextCatalog, $ServerObject.InstanceName + $confirmationMessage = $script:localizedData.DatabaseDefault_SetFullTextCatalog_ShouldProcessVerboseWarning -f $Name, $DefaultFullTextCatalog + $captionMessage = $script:localizedData.DatabaseDefault_SetFullTextCatalog_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage)) + { + $DatabaseObject.SetDefaultFullTextCatalog($DefaultFullTextCatalog) + $wasUpdate = $true + } + } + + if ($wasUpdate) + { + Write-Verbose -Message ($script:localizedData.DatabaseDefault_Updated -f $Name) + } + + if ($PassThru.IsPresent) + { + return $DatabaseObject + } + } + catch + { + $errorMessage = $script:localizedData.DatabaseDefault_SetFailed -f $Name, $ServerObject.InstanceName + + $exception = [System.InvalidOperationException]::new($errorMessage, $_.Exception) + + $PSCmdlet.ThrowTerminatingError( + [System.Management.Automation.ErrorRecord]::new( + $exception, + 'SSDDD0003', # cSpell: disable-line + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $Name + ) + ) + } + } +} diff --git a/source/en-US/SqlServerDsc.strings.psd1 b/source/en-US/SqlServerDsc.strings.psd1 index 8a24bf0219..c9af4710d5 100644 --- a/source/en-US/SqlServerDsc.strings.psd1 +++ b/source/en-US/SqlServerDsc.strings.psd1 @@ -371,6 +371,23 @@ ConvertFrom-StringData @' Database_RecoveryModelWrong = The database '{0}' exists and has the recovery model '{1}', but expected it to have the recovery model '{2}'. Database_OwnerNameWrong = The database '{0}' exists and has the owner '{1}', but expected it to have the owner '{2}'. + ## Set-SqlDscDatabaseDefault + DatabaseDefault_Set = Setting default objects of database '{0}' on instance '{1}'. (SSDDD0001) + DatabaseDefault_Updated = Database '{0}' default objects were updated successfully. (SSDDD0002) + DatabaseDefault_SetFailed = Failed to set default objects of database '{0}' on instance '{1}'. (SSDDD0003) + DatabaseDefault_SetFileGroup_ShouldProcessVerboseDescription = Setting the default filegroup of database '{0}' to '{1}' on instance '{2}'. + DatabaseDefault_SetFileGroup_ShouldProcessVerboseWarning = Are you sure you want to set the default filegroup of database '{0}' to '{1}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + DatabaseDefault_SetFileGroup_ShouldProcessCaption = Set database default filegroup + DatabaseDefault_SetFileStreamFileGroup_ShouldProcessVerboseDescription = Setting the default FILESTREAM filegroup of database '{0}' to '{1}' on instance '{2}'. + DatabaseDefault_SetFileStreamFileGroup_ShouldProcessVerboseWarning = Are you sure you want to set the default FILESTREAM filegroup of database '{0}' to '{1}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + DatabaseDefault_SetFileStreamFileGroup_ShouldProcessCaption = Set database default FILESTREAM filegroup + DatabaseDefault_SetFullTextCatalog_ShouldProcessVerboseDescription = Setting the default Full-Text catalog of database '{0}' to '{1}' on instance '{2}'. + DatabaseDefault_SetFullTextCatalog_ShouldProcessVerboseWarning = Are you sure you want to set the default Full-Text catalog of database '{0}' to '{1}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + DatabaseDefault_SetFullTextCatalog_ShouldProcessCaption = Set database default Full-Text catalog + ## Get-AgentAlertObject Get_AgentAlertObject_GettingAlert = Getting SQL Agent Alert '{0}'. (GAAO0001) diff --git a/tests/Integration/Commands/Set-SqlDscDatabaseDefault.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabaseDefault.Integration.Tests.ps1 new file mode 100644 index 0000000000..e117581b37 --- /dev/null +++ b/tests/Integration/Commands/Set-SqlDscDatabaseDefault.Integration.Tests.ps1 @@ -0,0 +1,125 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + +Describe 'Set-SqlDscDatabaseDefault' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + + # Test database names + $script:testDatabaseName = 'SqlDscTestSetDatabaseDefault_' + (Get-Random) + + # Create test database for the integration tests + $script:testDatabaseObject = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + + # Create additional filegroup for testing (needed for setting default filegroup) + $script:testFileGroupName = 'TestFileGroup_' + (Get-Random) + $script:serverObject.Databases[$script:testDatabaseName].Query("ALTER DATABASE [$script:testDatabaseName] ADD FILEGROUP [$script:testFileGroupName]") + + # Add a file to the filegroup so it can be set as default + $script:testFileName = 'TestFile_' + (Get-Random) + # Resolve instance default data path in a version-agnostic way + $dataRoot = $script:serverObject.Settings.DefaultFile + if (-not $dataRoot) { $dataRoot = $script:serverObject.Information.MasterDBPath } + $script:testFilePath = Join-Path -Path $dataRoot -ChildPath "$script:testFileName.ndf" + $script:serverObject.Databases[$script:testDatabaseName].Query("ALTER DATABASE [$script:testDatabaseName] ADD FILE (NAME = '$script:testFileName', FILENAME = '$script:testFilePath') TO FILEGROUP [$script:testFileGroupName]") + } + + AfterAll { + # Disconnect from the database engine. + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + + # Stopping the named instance SQL Server service after running tests. + Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + } + + Context 'When using the DatabaseObject parameter' { + It 'Should set the default filegroup without throwing an error' { + $null = Set-SqlDscDatabaseDefault -DatabaseObject $script:testDatabaseObject -DefaultFileGroup $script:testFileGroupName -Force + + # Verify the change was applied + $script:testDatabaseObject.Refresh() + $script:testDatabaseObject.DefaultFileGroup | Should -Be $script:testFileGroupName + } + + It 'Should reset the default filegroup back to PRIMARY' { + $null = Set-SqlDscDatabaseDefault -DatabaseObject $script:testDatabaseObject -DefaultFileGroup 'PRIMARY' -Force + + # Verify the change was applied + $script:testDatabaseObject.Refresh() + $script:testDatabaseObject.DefaultFileGroup | Should -Be 'PRIMARY' + } + } + + Context 'When using the ServerObject parameter' { + It 'Should set the default filegroup using server object and database name' { + $null = Set-SqlDscDatabaseDefault -ServerObject $script:serverObject -Name $script:testDatabaseName -DefaultFileGroup $script:testFileGroupName -Force + + # Verify the change was applied by refreshing the database object + $script:testDatabaseObject.Refresh() + $script:testDatabaseObject.DefaultFileGroup | Should -Be $script:testFileGroupName + } + + It 'Should return the database object when PassThru is specified' { + $result = Set-SqlDscDatabaseDefault -ServerObject $script:serverObject -Name $script:testDatabaseName -DefaultFileGroup 'PRIMARY' -PassThru -Force + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be $script:testDatabaseName + $result.DefaultFileGroup | Should -Be 'PRIMARY' + } + } + + Context 'When the command fails' { + It 'Should throw an error when trying to set a non-existent filegroup as default' { + { Set-SqlDscDatabaseDefault -DatabaseObject $script:testDatabaseObject -DefaultFileGroup 'NonExistentFileGroup' -Force } | Should -Throw + } + + It 'Should throw an error when database is not found' { + { Set-SqlDscDatabaseDefault -ServerObject $script:serverObject -Name 'NonExistentDatabase' -DefaultFileGroup 'PRIMARY' -Force } | Should -Throw + } + } + + Context 'After all tests are completed' { + It 'Should clean up the test database' { + $null = Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + } + } +} diff --git a/tests/Unit/Public/Set-SqlDscDatabaseDefault.Tests.ps1 b/tests/Unit/Public/Set-SqlDscDatabaseDefault.Tests.ps1 new file mode 100644 index 0000000000..17d668b945 --- /dev/null +++ b/tests/Unit/Public/Set-SqlDscDatabaseDefault.Tests.ps1 @@ -0,0 +1,366 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Set-SqlDscDatabaseDefault' -Tag 'Public' { + Context 'When command is called' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + ExpectedParameterSetName = 'ServerObject' + ExpectedParameters = '-ServerObject -Name [-DefaultFileGroup ] [-DefaultFileStreamFileGroup ] [-DefaultFullTextCatalog ] [-Force] [-Refresh] [-PassThru] [-WhatIf] [-Confirm] []' + } + @{ + ExpectedParameterSetName = 'DatabaseObject' + ExpectedParameters = '-DatabaseObject [-DefaultFileGroup ] [-DefaultFileStreamFileGroup ] [-DefaultFullTextCatalog ] [-Force] [-PassThru] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Set-SqlDscDatabaseDefault').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + + It 'Should have Name as a mandatory parameter in ServerObject parameter set' { + $parameterInfo = (Get-Command -Name 'Set-SqlDscDatabaseDefault').Parameters['Name'] + $parameterInfo.Attributes.Where({ $_.TypeId -eq [System.Management.Automation.ParameterAttribute] -and $_.ParameterSetName -eq 'ServerObject' }).Mandatory | Should -BeTrue + } + + It 'Should have ServerObject as a mandatory parameter in ServerObject parameter set' { + $parameterInfo = (Get-Command -Name 'Set-SqlDscDatabaseDefault').Parameters['ServerObject'] + $parameterInfo.Attributes.Where({ $_.TypeId -eq [System.Management.Automation.ParameterAttribute] -and $_.ParameterSetName -eq 'ServerObject' }).Mandatory | Should -BeTrue + } + + It 'Should have DatabaseObject as a mandatory parameter in DatabaseObject parameter set' { + $parameterInfo = (Get-Command -Name 'Set-SqlDscDatabaseDefault').Parameters['DatabaseObject'] + $parameterInfo.Attributes.Where({ $_.TypeId -eq [System.Management.Automation.ParameterAttribute] -and $_.ParameterSetName -eq 'DatabaseObject' }).Mandatory | Should -BeTrue + } + + It 'Should support ShouldProcess' { + $commandInfo = Get-Command -Name 'Set-SqlDscDatabaseDefault' + $commandInfo.Parameters['WhatIf'] | Should -Not -BeNullOrEmpty + $commandInfo.Parameters['Confirm'] | Should -Not -BeNullOrEmpty + } + } + + Context 'When using parameter set ServerObject' { + Context 'When database exists' { + BeforeAll { + Mock -CommandName Get-SqlDscDatabase -MockWith { + if ($Name -eq 'TestDatabase') { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + return $mockDatabaseObject + } + else { + throw "Database '$Name' was not found." + } + } + } + + It 'Should set default filegroup when DefaultFileGroup parameter is specified' { + InModuleScope -ScriptBlock { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + + # Mock the SetDefaultFileGroup method on the database object that will be returned + Mock -CommandName Get-SqlDscDatabase -MockWith { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileGroup' -Value 'PRIMARY' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileGroup = $fileGroupName + } -Force + return $mockDatabaseObject + } + + $null = Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'TestDatabase' -DefaultFileGroup 'NewFileGroup' -Force + + # Verify that Get-SqlDscDatabase was called + Should -Invoke -CommandName Get-SqlDscDatabase -Exactly -Times 1 -Scope It + } + } + + It 'Should set default FILESTREAM filegroup when DefaultFileStreamFileGroup parameter is specified' { + InModuleScope -ScriptBlock { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + + Mock -CommandName Get-SqlDscDatabase -MockWith { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileStreamFileGroup' -Value 'FileStreamGroup' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileStreamFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileStreamFileGroup = $fileGroupName + } -Force + return $mockDatabaseObject + } + + $null = Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'TestDatabase' -DefaultFileStreamFileGroup 'NewFileStreamGroup' -Force + + Should -Invoke -CommandName Get-SqlDscDatabase -Exactly -Times 1 -Scope It + } + } + + It 'Should set default Full-Text catalog when DefaultFullTextCatalog parameter is specified' { + InModuleScope -ScriptBlock { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + + Mock -CommandName Get-SqlDscDatabase -MockWith { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFullTextCatalog' -Value 'FTCatalog' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFullTextCatalog' -Value { + param($catalogName) + $this.DefaultFullTextCatalog = $catalogName + } -Force + return $mockDatabaseObject + } + + $null = Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'TestDatabase' -DefaultFullTextCatalog 'NewFTCatalog' -Force + + Should -Invoke -CommandName Get-SqlDscDatabase -Exactly -Times 1 -Scope It + } + } + + It 'Should return database object when PassThru is specified' { + InModuleScope -ScriptBlock { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileGroup' -Value 'PRIMARY' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileGroup = $fileGroupName + } -Force + + Mock -CommandName Get-SqlDscDatabase -MockWith { return $mockDatabaseObject } + + $result = Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'TestDatabase' -DefaultFileGroup 'PassThruTest' -PassThru -Force + $result | Should -Be $mockDatabaseObject + $result.DefaultFileGroup | Should -Be 'PassThruTest' + + Should -Invoke -CommandName Get-SqlDscDatabase -Exactly -Times 1 -Scope It + } + } + } + + Context 'When database does not exist' { + It 'Should throw an exception when database is not found' { + InModuleScope -ScriptBlock { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + + # Mock Get-SqlDscDatabase to throw the same error it would throw when a database is not found + Mock -CommandName Get-SqlDscDatabase -MockWith { + if ($ErrorAction -eq 'Stop') { + $missingDatabaseMessage = "Database '$Name' was not found." + $writeErrorParameters = @{ + Message = $missingDatabaseMessage + Category = 'ObjectNotFound' + ErrorId = 'GSDD0001' + TargetObject = $Name + } + Write-Error @writeErrorParameters -ErrorAction 'Stop' + } + } + + { Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'NonExistentDatabase' -DefaultFileGroup 'TestGroup' -Force } | Should -Throw -ExpectedMessage "*Database 'NonExistentDatabase' on instance 'TestInstance'*" + + Should -Invoke -CommandName Get-SqlDscDatabase -Exactly -Times 1 -Scope It + } + } + } + } + + Context 'When using parameter set DatabaseObject' { + It 'Should set default filegroup when DefaultFileGroup parameter is specified' { + InModuleScope -ScriptBlock { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileGroup' -Value 'PRIMARY' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileGroup = $fileGroupName + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + + $null = Set-SqlDscDatabaseDefault -DatabaseObject $mockDatabaseObject -DefaultFileGroup 'DirectFileGroup' -Force + $mockDatabaseObject.DefaultFileGroup | Should -Be 'DirectFileGroup' + } + } + + It 'Should set default FILESTREAM filegroup when DefaultFileStreamFileGroup parameter is specified' { + InModuleScope -ScriptBlock { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileStreamFileGroup' -Value 'FileStreamGroup' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileStreamFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileStreamFileGroup = $fileGroupName + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + + $null = Set-SqlDscDatabaseDefault -DatabaseObject $mockDatabaseObject -DefaultFileStreamFileGroup 'DirectStreamGroup' -Force + $mockDatabaseObject.DefaultFileStreamFileGroup | Should -Be 'DirectStreamGroup' + } + } + + It 'Should set default Full-Text catalog when DefaultFullTextCatalog parameter is specified' { + InModuleScope -ScriptBlock { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFullTextCatalog' -Value 'FTCatalog' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFullTextCatalog' -Value { + param($catalogName) + $this.DefaultFullTextCatalog = $catalogName + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + + $null = Set-SqlDscDatabaseDefault -DatabaseObject $mockDatabaseObject -DefaultFullTextCatalog 'DirectFTCatalog' -Force + $mockDatabaseObject.DefaultFullTextCatalog | Should -Be 'DirectFTCatalog' + } + } + + It 'Should return database object when PassThru is specified' { + InModuleScope -ScriptBlock { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileGroup' -Value 'PRIMARY' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileGroup = $fileGroupName + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + + $result = Set-SqlDscDatabaseDefault -DatabaseObject $mockDatabaseObject -DefaultFileGroup 'PassThruDirect' -PassThru -Force + $result | Should -Be $mockDatabaseObject + $result.DefaultFileGroup | Should -Be 'PassThruDirect' + } + } + } + + Context 'When using ShouldProcess' { + It 'Should not modify database when WhatIf is specified' { + InModuleScope -ScriptBlock { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileGroup' -Value 'PRIMARY' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetDefaultFileGroup' -Value { + param($fileGroupName) + $this.DefaultFileGroup = $fileGroupName + } -Force + + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockDatabaseObject + } + } -Force + + $originalDefaultFileGroup = $mockDatabaseObject.DefaultFileGroup + + Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'TestDatabase' -DefaultFileGroup 'WhatIfTest' -WhatIf + + $mockDatabaseObject.DefaultFileGroup | Should -Be $originalDefaultFileGroup + } + } + } + + Context 'When no parameters that change defaults are specified' { + It 'Should not call any SetDefault methods' { + InModuleScope -ScriptBlock { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'DefaultFileGroup' -Value 'PRIMARY' -Force + + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockDatabaseObject + } + } -Force + + $originalDefaultFileGroup = $mockDatabaseObject.DefaultFileGroup + + Set-SqlDscDatabaseDefault -ServerObject $mockServerObject -Name 'TestDatabase' -Force + + $mockDatabaseObject.DefaultFileGroup | Should -Be $originalDefaultFileGroup + } + } + } +} diff --git a/tests/Unit/Stubs/SMO.cs b/tests/Unit/Stubs/SMO.cs index dcc927c45f..fa07aee1a6 100644 --- a/tests/Unit/Stubs/SMO.cs +++ b/tests/Unit/Stubs/SMO.cs @@ -567,6 +567,8 @@ public class Database public DateTime CreateDate; public DatabaseEncryptionKey DatabaseEncryptionKey; public string DefaultFileStreamFileGroup; + public string DefaultFileGroup = "PRIMARY"; + public string DefaultFullTextCatalog; public bool EncryptionEnabled = false; public Hashtable FileGroups; public string FilestreamDirectoryName; @@ -617,6 +619,33 @@ public void Grant( Microsoft.SqlServer.Management.Smo.DatabasePermissionSet perm public void Deny( Microsoft.SqlServer.Management.Smo.DatabasePermissionSet permission, string granteeName ) { } + + public void SetDefaultFileGroup( string fileGroupName ) + { + if (fileGroupName == "ThrowException") + { + throw new System.Exception("Failed to set default filegroup"); + } + this.DefaultFileGroup = fileGroupName; + } + + public void SetDefaultFileStreamFileGroup( string fileGroupName ) + { + if (fileGroupName == "ThrowException") + { + throw new System.Exception("Failed to set default FILESTREAM filegroup"); + } + this.DefaultFileStreamFileGroup = fileGroupName; + } + + public void SetDefaultFullTextCatalog( string catalogName ) + { + if (catalogName == "ThrowException") + { + throw new System.Exception("Failed to set default Full-Text catalog"); + } + this.DefaultFullTextCatalog = catalogName; + } } // TypeName: Microsoft.SqlServer.Management.Smo.User @@ -1654,3 +1683,4 @@ public static Alert CreateTypeInstance() #endregion } +