diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/ConfigureDacDeployOptionsAnnotation.cs b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/ConfigureDacDeployOptionsAnnotation.cs
new file mode 100644
index 00000000..70ec72c9
--- /dev/null
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/ConfigureDacDeployOptionsAnnotation.cs
@@ -0,0 +1,11 @@
+using Microsoft.SqlServer.Dac;
+
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// Represents a metadata annotation that specifies dacpac deployment options.
+///
+/// deployment options
+public record ConfigureDacDeployOptionsAnnotation(Action ConfigureDeploymentOptions) : IResourceAnnotation
+{
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/DacpacDeployer.cs b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/DacpacDeployer.cs
index 681bcfa5..9afb22e7 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/DacpacDeployer.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/DacpacDeployer.cs
@@ -8,12 +8,12 @@ namespace CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects;
///
internal class DacpacDeployer : IDacpacDeployer
{
- ///
- public void Deploy(string dacpacPath, string targetConnectionString, string targetDatabaseName, ILogger deploymentLogger, CancellationToken cancellationToken)
+ ///
+ public void Deploy(string dacpacPath, DacDeployOptions options, string targetConnectionString, string targetDatabaseName, ILogger deploymentLogger, CancellationToken cancellationToken)
{
- var dacPackage = DacPackage.Load(dacpacPath, DacSchemaModelStorageType.Memory);
+ using var dacPackage = DacPackage.Load(dacpacPath, DacSchemaModelStorageType.Memory);
var dacServices = new DacServices(targetConnectionString);
dacServices.Message += (sender, args) => deploymentLogger.LogInformation(args.Message.ToString());
- dacServices.Deploy(dacPackage, targetDatabaseName, true, new DacDeployOptions(), cancellationToken);
+ dacServices.Deploy(dacPackage, targetDatabaseName, true, options, cancellationToken);
}
-}
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/IDacpacDeployer.cs b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/IDacpacDeployer.cs
index 4e120737..a9d9b924 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/IDacpacDeployer.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/IDacpacDeployer.cs
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
+using Microsoft.SqlServer.Dac;
namespace CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects;
@@ -12,9 +13,10 @@ internal interface IDacpacDeployer
/// using the provided database name.
///
/// Path to the .dacpac file to deploy.
+ /// Instance of that specifies properties that affect various aspects of the deployment.
/// Connection string to the SQL Server.
/// Name of the target database to deploy to.
/// An to write the deployment log to.
/// A that can be used to cancel the deployment operation.
- void Deploy(string dacpacPath, string targetConnectionString, string targetDatabaseName, ILogger deploymentLogger, CancellationToken cancellationToken);
+ void Deploy(string dacpacPath, DacDeployOptions options, string targetConnectionString, string targetDatabaseName, ILogger deploymentLogger, CancellationToken cancellationToken);
}
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/PublicAPI.Unshipped.txt b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/PublicAPI.Unshipped.txt
index 074c6ad1..d5d6b090 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/PublicAPI.Unshipped.txt
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/PublicAPI.Unshipped.txt
@@ -1,2 +1,6 @@
#nullable enable
-
+Aspire.Hosting.ApplicationModel.ConfigureDacDeployOptionsAnnotation
+Aspire.Hosting.ApplicationModel.ConfigureDacDeployOptionsAnnotation.ConfigureDacDeployOptionsAnnotation(System.Action! ConfigureDeploymentOptions) -> void
+Aspire.Hosting.ApplicationModel.ConfigureDacDeployOptionsAnnotation.ConfigureDeploymentOptions.get -> System.Action!
+Aspire.Hosting.ApplicationModel.ConfigureDacDeployOptionsAnnotation.ConfigureDeploymentOptions.init -> void
+static Aspire.Hosting.SqlProjectBuilderExtensions.WithConfigureDacDeployOptions(this Aspire.Hosting.ApplicationModel.IResourceBuilder! builder, System.Action! configureDeploymentOptions) -> Aspire.Hosting.ApplicationModel.IResourceBuilder!
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/README.md b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/README.md
index 3e083cbf..21df7927 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/README.md
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/README.md
@@ -45,5 +45,21 @@ builder.AddSqlProject("mysqlproj")
.WithDacpac("path/to/mysqlproj.dacpac")
.WithReference(sql);
+builder.Build().Run();
+```
+
+## Deployment options support
+Define options that affect the behavior of package deployment.
+
+```csharp
+var builder = DistributedApplication.CreateBuilder(args);
+
+var sql = builder.AddSqlServer("sql")
+ .AddDatabase("test");
+
+builder.AddSqlProject("mysqlproj")
+ .WithConfigureDacDeployOptions(options => options.IncludeCompositeObjects = true)
+ .WithReference(sql);
+
builder.Build().Run();
```
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectBuilderExtensions.cs
index 475cd2d9..4ea2b74d 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectBuilderExtensions.cs
@@ -3,6 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects;
+using Microsoft.SqlServer.Dac;
namespace Aspire.Hosting;
@@ -72,6 +73,21 @@ public static IResourceBuilder WithDacpac(this IResourceBuil
return builder.WithAnnotation(new DacpacMetadataAnnotation(dacpacPath));
}
+ ///
+ /// Adds a delegate annotation for configuring dacpac deployment options to the .
+ ///
+ /// An representing the SQL Server Database project.
+ /// The delegate for configuring dacpac deployment options
+ /// An that can be used to further customize the resource.
+ public static IResourceBuilder WithConfigureDacDeployOptions(this IResourceBuilder builder, Action configureDeploymentOptions)
+ {
+ ArgumentNullException.ThrowIfNull(builder, nameof(builder));
+ ArgumentNullException.ThrowIfNull(configureDeploymentOptions);
+
+ return builder
+ .WithAnnotation(new ConfigureDacDeployOptionsAnnotation(configureDeploymentOptions));
+ }
+
///
/// Publishes the SQL Server Database project to the target .
///
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectPublishService.cs b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectPublishService.cs
index 98716a32..3d37d0c8 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectPublishService.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectPublishService.cs
@@ -21,6 +21,8 @@ await resourceNotificationService.PublishUpdateAsync(sqlProject,
return;
}
+ var options = sqlProject.GetDacpacDeployOptions();
+
var connectionString = await target.ConnectionStringExpression.GetValueAsync(cancellationToken);
if (connectionString is null)
{
@@ -33,7 +35,7 @@ await resourceNotificationService.PublishUpdateAsync(sqlProject,
await resourceNotificationService.PublishUpdateAsync(sqlProject,
state => state with { State = new ResourceStateSnapshot("Publishing", KnownResourceStateStyles.Info) });
- deployer.Deploy(dacpacPath, connectionString, target.DatabaseName, logger, cancellationToken);
+ deployer.Deploy(dacpacPath, options, connectionString, target.DatabaseName, logger, cancellationToken);
await resourceNotificationService.PublishUpdateAsync(sqlProject,
state => state with { State = new ResourceStateSnapshot(KnownResourceStates.Finished, KnownResourceStateStyles.Success) });
diff --git a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectResource.cs b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectResource.cs
index 004f84cd..68391fde 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectResource.cs
@@ -1,4 +1,5 @@
using Microsoft.Build.Evaluation;
+using Microsoft.SqlServer.Dac;
namespace Aspire.Hosting.ApplicationModel;
@@ -33,4 +34,16 @@ internal string GetDacpacPath()
throw new InvalidOperationException($"Unable to locate SQL Server Database project package for resource {Name}.");
}
+
+ internal DacDeployOptions GetDacpacDeployOptions()
+ {
+ var options = new DacDeployOptions();
+
+ if (this.TryGetLastAnnotation(out var configureAnnotation))
+ {
+ configureAnnotation.ConfigureDeploymentOptions(options);
+ }
+
+ return options;
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/AddSqlProjectTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/AddSqlProjectTests.cs
index 559e3214..df7d0f56 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/AddSqlProjectTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/AddSqlProjectTests.cs
@@ -1,4 +1,5 @@
using Aspire.Hosting;
+using Microsoft.SqlServer.Dac;
namespace CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests;
@@ -47,6 +48,53 @@ public void AddSqlProject_WithExplicitPath()
Assert.True(File.Exists(dacpacPath));
}
+ [Fact]
+ public void AddSqlProject_WithoutDeploymentOptions()
+ {
+ // Arrange
+ var appBuilder = DistributedApplication.CreateBuilder();
+
+ appBuilder.AddSqlProject("MySqlProject");
+
+ // Act
+ using var app = appBuilder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ // Assert
+ var sqlProjectResource = Assert.Single(appModel.Resources.OfType());
+ Assert.Equal("MySqlProject", sqlProjectResource.Name);
+
+ Assert.False(sqlProjectResource.TryGetLastAnnotation(out ConfigureDacDeployOptionsAnnotation? _));
+
+ var options = sqlProjectResource.GetDacpacDeployOptions();
+ Assert.NotNull(options);
+ Assert.Equivalent(new DacDeployOptions(), options);
+ }
+
+ [Fact]
+ public void AddSqlProject_WithDeploymentOptions()
+ {
+ // Arrange
+ var appBuilder = DistributedApplication.CreateBuilder();
+ Action configureAction = options => options.IncludeCompositeObjects = true;
+
+ appBuilder.AddSqlProject("MySqlProject").WithConfigureDacDeployOptions(configureAction);
+
+ // Act
+ using var app = appBuilder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ // Assert
+ var sqlProjectResource = Assert.Single(appModel.Resources.OfType());
+ Assert.Equal("MySqlProject", sqlProjectResource.Name);
+
+ Assert.True(sqlProjectResource.TryGetLastAnnotation(out ConfigureDacDeployOptionsAnnotation? configureDacDeployOptionsAnnotation));
+ Assert.Same(configureAction, configureDacDeployOptionsAnnotation.ConfigureDeploymentOptions);
+
+ var options = sqlProjectResource.GetDacpacDeployOptions();
+ Assert.True(options.IncludeCompositeObjects);
+ }
+
[Fact]
public void PublishTo_AddsRequiredServices()
{