diff --git a/src/MSBuild.Sdk.SqlProj.Aspire/DataTierApplicationBuilderExtensions.cs b/src/MSBuild.Sdk.SqlProj.Aspire/DataTierApplicationBuilderExtensions.cs deleted file mode 100644 index 6d76c376..00000000 --- a/src/MSBuild.Sdk.SqlProj.Aspire/DataTierApplicationBuilderExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Aspire.Hosting.ApplicationModel; -using Aspire.Hosting.Lifecycle; -using Microsoft.Build.Locator; -using MSBuild.Sdk.SqlProj.Aspire; - -namespace Aspire.Hosting; - -public static class DataTierApplicationBuilderExtensions -{ - /// - /// Adds a data-tier application resource to the application based on a referenced MSBuild.Sdk.SqlProj project. - /// - /// Type that represents the project that produces the data-tier application package (.dacpac file). - /// An instance to add the data-tier application to. - /// Name of the resource. - /// An that can be used to further customize the resource. - public static IResourceBuilder AddDataTierApplication(this IDistributedApplicationBuilder builder, string name) - where TProject : IProjectMetadata, new() - { - if (!MSBuildLocator.IsRegistered) - { - MSBuildLocator.RegisterDefaults(); - } - - var resource = new DataTierApplicationResource(name); - - return builder.AddResource(resource) - .WithAnnotation(new TProject()); - } - - /// - /// Adds a data-tier application resource to the application based on a data-tier application package file (.dacpac). - /// - /// An instance to add the data-tier application to. - /// Name of the resource. - /// Path to a data-tier application package file (.dacpac). - /// An that can be used to further customize the resource. - public static IResourceBuilder AddDataTierApplication(this IDistributedApplicationBuilder builder, string name, string dacpacPath) - { - var resource = new DataTierApplicationResource(name); - - if (!Path.IsPathRooted(dacpacPath)) - { - dacpacPath = Path.Combine(builder.AppHostDirectory, dacpacPath); - } - - return builder.AddResource(resource) - .WithAnnotation(new DacpacMetadataAnnotation(dacpacPath)); - } - - /// - /// Publishes the data-tier application to the target . - /// - /// An representing the data-tier application to publish. - /// An representing the target to publish the data-tier application to. - /// An that can be used to further customize the resource. - public static IResourceBuilder PublishTo( - this IResourceBuilder builder, IResourceBuilder target) - { - builder.ApplicationBuilder.Services.TryAddLifecycleHook(); - builder.WithAnnotation(new TargetDatabaseResourceAnnotation(target.Resource.Name), ResourceAnnotationMutationBehavior.Replace); - return builder; - } -} diff --git a/src/MSBuild.Sdk.SqlProj.Aspire/PublishDataTierApplicationLifecycleHook.cs b/src/MSBuild.Sdk.SqlProj.Aspire/PublishSqlProjectLifecycleHook.cs similarity index 72% rename from src/MSBuild.Sdk.SqlProj.Aspire/PublishDataTierApplicationLifecycleHook.cs rename to src/MSBuild.Sdk.SqlProj.Aspire/PublishSqlProjectLifecycleHook.cs index e3ecf21f..f58be331 100644 --- a/src/MSBuild.Sdk.SqlProj.Aspire/PublishDataTierApplicationLifecycleHook.cs +++ b/src/MSBuild.Sdk.SqlProj.Aspire/PublishSqlProjectLifecycleHook.cs @@ -1,4 +1,3 @@ -using Aspire.Hosting; using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Lifecycle; using Microsoft.Extensions.Logging; @@ -6,13 +5,13 @@ namespace MSBuild.Sdk.SqlProj.Aspire; -public class PublishDataTierApplicationLifecycleHook : IDistributedApplicationLifecycleHook +public class PublishSqlProjectLifecycleHook : IDistributedApplicationLifecycleHook { private readonly ResourceLoggerService _resourceLoggerService; private readonly ResourceNotificationService _resourceNotificationService; - public PublishDataTierApplicationLifecycleHook(ResourceLoggerService resourceLoggerService, - ResourceNotificationService resourceNotificationService, DistributedApplicationOptions options) + public PublishSqlProjectLifecycleHook(ResourceLoggerService resourceLoggerService, + ResourceNotificationService resourceNotificationService) { _resourceLoggerService = resourceLoggerService ?? throw new ArgumentNullException(nameof(resourceLoggerService)); _resourceNotificationService = resourceNotificationService ?? throw new ArgumentNullException(nameof(resourceNotificationService)); @@ -20,24 +19,24 @@ public PublishDataTierApplicationLifecycleHook(ResourceLoggerService resourceLog public async Task AfterResourcesCreatedAsync(DistributedApplicationModel application, CancellationToken cancellationToken) { - foreach (var dataTierApplication in application.Resources.OfType()) + foreach (var sqlProject in application.Resources.OfType()) { - var logger = _resourceLoggerService.GetLogger(dataTierApplication); + var logger = _resourceLoggerService.GetLogger(sqlProject); - var dacpacPath = dataTierApplication.GetDacpacPath(); + var dacpacPath = sqlProject.GetDacpacPath(); if (!File.Exists(dacpacPath)) { - logger.LogError("Data-tier application package not found at path {DacpacPath}.", dacpacPath); - await _resourceNotificationService.PublishUpdateAsync(dataTierApplication, + logger.LogError("SQL Server Database project package not found at path {DacpacPath}.", dacpacPath); + await _resourceNotificationService.PublishUpdateAsync(sqlProject, state => state with { State = new ResourceStateSnapshot("Failed", KnownResourceStateStyles.Error) }); continue; } - var targetDatabaseResourceName = dataTierApplication.Annotations.OfType().Single().TargetDatabaseResourceName; + var targetDatabaseResourceName = sqlProject.Annotations.OfType().Single().TargetDatabaseResourceName; var targetDatabaseResource = application.Resources.OfType().Single(r => r.Name == targetDatabaseResourceName); var connectionString = await targetDatabaseResource.ConnectionStringExpression.GetValueAsync(cancellationToken); - await _resourceNotificationService.PublishUpdateAsync(dataTierApplication, + await _resourceNotificationService.PublishUpdateAsync(sqlProject, state => state with { State = new ResourceStateSnapshot("Publishing", KnownResourceStateStyles.Info) }); try @@ -48,14 +47,14 @@ await _resourceNotificationService.PublishUpdateAsync(dataTierApplication, var dacpacPackage = DacPackage.Load(dacpacPath, DacSchemaModelStorageType.Memory); dacServices.Deploy(dacpacPackage, targetDatabaseResource.Name, true, new DacDeployOptions(), cancellationToken); - await _resourceNotificationService.PublishUpdateAsync(dataTierApplication, + await _resourceNotificationService.PublishUpdateAsync(sqlProject, state => state with { State = new ResourceStateSnapshot("Published", KnownResourceStateStyles.Success) }); } catch (Exception ex) { logger.LogError(ex, "Failed to publish database project."); - await _resourceNotificationService.PublishUpdateAsync(dataTierApplication, + await _resourceNotificationService.PublishUpdateAsync(sqlProject, state => state with { State = new ResourceStateSnapshot("Failed", KnownResourceStateStyles.Error) }); } } diff --git a/src/MSBuild.Sdk.SqlProj.Aspire/README.md b/src/MSBuild.Sdk.SqlProj.Aspire/README.md index c65e840a..6abab179 100644 --- a/src/MSBuild.Sdk.SqlProj.Aspire/README.md +++ b/src/MSBuild.Sdk.SqlProj.Aspire/README.md @@ -24,7 +24,7 @@ var builder = DistributedApplication.CreateBuilder(args); var sql = builder.AddSqlServer("sql") .AddDatabase("test"); -builder.AddDataTierApplication("mysqlproj") +builder.AddSqlProject("mysqlproj") .PublishTo(sql); builder.Build().Run(); @@ -33,7 +33,7 @@ builder.Build().Run(); Now when you run your .NET Aspire AppHost project you will see the SQL Database Project being published to the specified SQL Server. ## Local .dacpac file support -If you are sourcing your data-tier application package (.dacpac) file from somewhere other than a project reference, you can also specify the path to the .dacpac file directly: +If you are sourcing your .dacpac file from somewhere other than a project reference, you can also specify the path to the .dacpac file directly: ```csharp var builder = DistributedApplication.CreateBuilder(args); @@ -41,7 +41,8 @@ var builder = DistributedApplication.CreateBuilder(args); var sql = builder.AddSqlServer("sql") .AddDatabase("test"); -builder.AddDataTierApplication("mysqlproj", "path/to/mysqlproj.dacpac") +builder.AddSqlProject("mysqlproj") + .FromDacpac("path/to/mysqlproj.dacpac") .PublishTo(sql); builder.Build().Run(); diff --git a/src/MSBuild.Sdk.SqlProj.Aspire/SqlProjectBuilderExtensions.cs b/src/MSBuild.Sdk.SqlProj.Aspire/SqlProjectBuilderExtensions.cs new file mode 100644 index 00000000..3dcc6890 --- /dev/null +++ b/src/MSBuild.Sdk.SqlProj.Aspire/SqlProjectBuilderExtensions.cs @@ -0,0 +1,73 @@ +using Aspire.Hosting.ApplicationModel; +using Aspire.Hosting.Lifecycle; +using Microsoft.Build.Locator; +using MSBuild.Sdk.SqlProj.Aspire; + +namespace Aspire.Hosting; + +public static class SqlProjectBuilderExtensions +{ + /// + /// Adds a SQL Server Database Project resource to the application based on a referenced MSBuild.Sdk.SqlProj project. + /// + /// Type that represents the project that produces the .dacpac file. + /// An instance to add the SQL Server Database project to. + /// Name of the resource. + /// An that can be used to further customize the resource. + public static IResourceBuilder AddSqlProject(this IDistributedApplicationBuilder builder, string name) + where TProject : IProjectMetadata, new() + { + if (!MSBuildLocator.IsRegistered) + { + MSBuildLocator.RegisterDefaults(); + } + + var resource = new SqlProjectResource(name); + + return builder.AddResource(resource) + .WithAnnotation(new TProject()); + } + + /// + /// Adds a SQL Server Database Project resource to the application. + /// + /// An instance to add the SQL Server Database project to. + /// Name of the resource. + /// An that can be used to further customize the resource. + public static IResourceBuilder AddSqlProject(this IDistributedApplicationBuilder builder, string name) + { + var resource = new SqlProjectResource(name); + + return builder.AddResource(resource); + } + + /// + /// Specifies the path to the .dacpac file. + /// + /// An representing the SQL Server Database project. + /// Path to the .dacpac file. + /// An that can be used to further customize the resource. + public static IResourceBuilder FromDacpac(this IResourceBuilder builder, string dacpacPath) + { + if (!Path.IsPathRooted(dacpacPath)) + { + dacpacPath = Path.Combine(builder.ApplicationBuilder.AppHostDirectory, dacpacPath); + } + + return builder.WithAnnotation(new DacpacMetadataAnnotation(dacpacPath)); + } + + /// + /// Publishes the SQL Server Database project to the target . + /// + /// An representing the SQL Server Database project to publish. + /// An representing the target to publish the SQL Server Database project to. + /// An that can be used to further customize the resource. + public static IResourceBuilder PublishTo( + this IResourceBuilder builder, IResourceBuilder target) + { + builder.ApplicationBuilder.Services.TryAddLifecycleHook(); + builder.WithAnnotation(new TargetDatabaseResourceAnnotation(target.Resource.Name), ResourceAnnotationMutationBehavior.Replace); + return builder; + } +} diff --git a/src/MSBuild.Sdk.SqlProj.Aspire/DataTierApplicationResource.cs b/src/MSBuild.Sdk.SqlProj.Aspire/SqlProjectResource.cs similarity index 78% rename from src/MSBuild.Sdk.SqlProj.Aspire/DataTierApplicationResource.cs rename to src/MSBuild.Sdk.SqlProj.Aspire/SqlProjectResource.cs index 51685563..654e6fea 100644 --- a/src/MSBuild.Sdk.SqlProj.Aspire/DataTierApplicationResource.cs +++ b/src/MSBuild.Sdk.SqlProj.Aspire/SqlProjectResource.cs @@ -4,7 +4,7 @@ namespace MSBuild.Sdk.SqlProj.Aspire; -public sealed class DataTierApplicationResource(string name) : Resource(name) +public sealed class SqlProjectResource(string name) : Resource(name) { public string GetDacpacPath() { @@ -22,6 +22,6 @@ public string GetDacpacPath() return dacpacMetadata.DacpacPath; } - throw new InvalidOperationException($"Unable to locate data-tier application package for resource {Name}."); + throw new InvalidOperationException($"Unable to locate SQL Server Database project package for resource {Name}."); } } diff --git a/test/TestAspireHost/Program.cs b/test/TestAspireHost/Program.cs index bbdf166b..7bb79369 100644 --- a/test/TestAspireHost/Program.cs +++ b/test/TestAspireHost/Program.cs @@ -3,10 +3,11 @@ var sql = builder.AddSqlServer("sql") .AddDatabase("test"); -builder.AddDataTierApplication("testproject") +builder.AddSqlProject("testproject") .PublishTo(sql); -builder.AddDataTierApplication("testprojectwithwarnings", "../TestProjectWithWarnings/bin/Debug/netstandard2.0/TestProjectWithWarnings.dacpac") +builder.AddSqlProject("testprojectwithwarnings") + .FromDacpac("../TestProjectWithWarnings/bin/Debug/netstandard2.0/TestProjectWithWarnings.dacpac") .PublishTo(sql); builder.Build().Run();