Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/DacFXTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public static async System.Threading.Tasks.Task<int> Main(string[] args)
};

var provider = new ServiceCollection().AddEfpt(reverseEngineerCommandOptions, new List<string>(), new List<string>(), new List<string>()).BuildServiceProvider();
var procedureModelFactory = provider.GetRequiredService<IProcedureModelFactory>();
var functionModelFactory = provider.GetRequiredService<IFunctionModelFactory>();
var procedureModelFactory = provider.GetService<IProcedureModelFactory>();
var functionModelFactory = provider.GetService<IFunctionModelFactory>();
var databaseModelFactory = provider.GetRequiredService<IDatabaseModelFactory>();
var builder = new TableListBuilder(reverseEngineerCommandOptions, procedureModelFactory, functionModelFactory, databaseModelFactory, schemas ?? []);

Expand Down Expand Up @@ -215,10 +215,10 @@ public static async System.Threading.Tasks.Task<int> Main(string[] args)
if (args.Length == 5
&& (args[0] == "merge"))
{
MergeGenerator.Generate(args[1], args[2], args[3], args[4]);
var result = MergeGenerator.Generate(args[1], args[2], args[3], args[4]);

await Console.Out.WriteLineAsync("Result:");
await Console.Out.WriteLineAsync("OK");
await Console.Out.WriteLineAsync(result);

return 0;
}
Expand Down
8 changes: 5 additions & 3 deletions src/DacFXToolLib/MergeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace DacFXToolLib
{
public static class MergeGenerator
{
public static void Generate(string projectPath, string connectionString, string tableName, string schema)
public static string Generate(string projectPath, string connectionString, string tableName, string schema)
{
var script = ReadScript();

Expand All @@ -28,10 +28,10 @@ public static void Generate(string projectPath, string connectionString, string

connection.Close();

WriteResult(projectPath, tableName, result);
return WriteResult(projectPath, tableName, result);
}

private static void WriteResult(string projectPath, string tableName, object result)
private static string WriteResult(string projectPath, string tableName, object result)
{
var projectDirectory = Path.GetDirectoryName(projectPath);

Expand All @@ -48,6 +48,8 @@ private static void WriteResult(string projectPath, string tableName, object res
}

File.WriteAllText(outputPath, result.ToString(), Encoding.UTF8);

return outputPath;
}

private static string ReadScript()
Expand Down
15 changes: 13 additions & 2 deletions src/DacFXToolLib/ServiceProviderBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.SqlServer.Design.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;

Expand Down Expand Up @@ -38,7 +39,12 @@ public static IServiceCollection AddEfpt(this IServiceCollection serviceCollecti
switch (options.DatabaseType)
{
case DatabaseType.SQLServerDacpac:
AddSqlServerProviderServices(serviceCollection, options); break;
AddSqlServerProviderServices(serviceCollection, options);
break;

case DatabaseType.SQLServer:
AddSqlServerProviderServices(serviceCollection, options);
break;

default:
throw new ArgumentOutOfRangeException(nameof(options), $"unsupported database type: {options.DatabaseType}");
Expand All @@ -55,7 +61,6 @@ private static void AddSqlServerProviderServices(IServiceCollection serviceColle
#if CORE100
serviceCollection.AddSingleton(new SqlServerSingletonOptions());
#endif

if (options.DatabaseType == DatabaseType.SQLServerDacpac)
{
var excludedIndexes = options.Tables?.Select(t => new { t.Name, t.ExcludedIndexes });
Expand All @@ -79,6 +84,12 @@ private static void AddSqlServerProviderServices(IServiceCollection serviceColle
MergeDacpacs = options.MergeDacpacs,
});
}

if (options.DatabaseType == DatabaseType.SQLServer)
{
serviceCollection.AddSingleton(options);
serviceCollection.AddSingleton<IDatabaseModelFactory, SqlServerDatabaseModelFactory>();
}
}
}
}
10 changes: 5 additions & 5 deletions src/DacFXToolLib/TableListBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DacFXToolLib.Common;
using DacFXToolLib.Common;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
using RevEng.Core.Abstractions;
Expand All @@ -8,8 +8,8 @@ namespace DacFXToolLib
{
public class TableListBuilder
{
private readonly IProcedureModelFactory procedureModelFactory;
private readonly IFunctionModelFactory functionModelFactory;
private readonly IProcedureModelFactory? procedureModelFactory;
private readonly IFunctionModelFactory? functionModelFactory;
private readonly IDatabaseModelFactory databaseModelFactory;

private readonly SchemaInfo[] schemas;
Expand All @@ -19,8 +19,8 @@ public class TableListBuilder

public TableListBuilder(
ReverseEngineerCommandOptions options,
IProcedureModelFactory procedureModelFactory,
IFunctionModelFactory functionModelFactory,
IProcedureModelFactory? procedureModelFactory,
IFunctionModelFactory? functionModelFactory,
IDatabaseModelFactory databaseModelFactory,
SchemaInfo[] schemas)
{
Expand Down
Binary file modified src/Lib/dacfxtool.exe.zip
Binary file not shown.
3 changes: 2 additions & 1 deletion src/Vsix/Commands/SeedCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)

if (project != null)
{
await VS.MessageBox.ShowConfirmAsync("Seed functionality is not yet implemented.");
var handler = new SeedHandler();
await handler.GenerateSeedScriptsAsync(project);
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/Vsix/Dialogs/PickServerDatabaseDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ public PickServerDatabaseDialog(
return;
}

if (allowedVersions.Count == 1
&& allowedVersions[0].Value == "Seed")
{
grdRow1.Height = new GridLength(0);
grdRow2.Height = new GridLength(0);
grdRow3.Height = new GridLength(0);
return;
}

foreach (var item in allowedVersions)
{
viewModel.CodeGenerationModeList.Add(item);
Expand Down
6 changes: 3 additions & 3 deletions src/Vsix/Handlers/ImportHandler.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using DacFXToolLib.Common;
using DacFXToolLib.Dab;
using Microsoft.VisualStudio.Shell.Interop;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using DacFXToolLib.Common;
using DacFXToolLib.Dab;
using Microsoft.VisualStudio.Shell.Interop;

namespace SqlProjectsPowerTools
{
Expand Down
10 changes: 10 additions & 0 deletions src/Vsix/Handlers/ProcessLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ public async Task<string> GetDabConfigPathAsync(string optionsPath, string conne
return filePath;
}

// merge "projectpath" "connectionString" "tableName" "schema"
public async Task<string> CreateMergeScriptAsync(string projectPath, string connectionString, string tablename, string schema)
{
var arguments = "merge " + " \"" + projectPath.Replace("\"", "\\\"") + "\" " + " \"" + connectionString.Replace("\"", "\\\"") + "\" \"" + tablename.Replace("\"", "\\\"") + "\" \"" + schema.Replace("\"", "\\\"") + "\"";
Comment thread
ErikEJ marked this conversation as resolved.

var result = await GetDiagramInternalAsync(arguments);

return result;
}

private static async Task<string> RunProcessAsync(ProcessStartInfo startInfo)
{
return await ExternalProcessLauncher.RunProcessAsync(startInfo);
Expand Down
209 changes: 209 additions & 0 deletions src/Vsix/Handlers/SeedHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using DacFXToolLib.Common;
using DacFXToolLib.Dab;

namespace SqlProjectsPowerTools
{
internal class SeedHandler
{
public async Task GenerateSeedScriptsAsync(Project project)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

try
{
if (await VSHelper.IsDebugModeAsync())
{
VSHelper.ShowError("Cannot generate code while debugging");
return;
}

var options = new DataApiBuilderOptions();

var info = await ChooseDataBaseConnectionAsync(options);

if (info.DatabaseModel == null)
{
return;
}

var dbInfo = await GetDatabaseInfoAsync(options);

if (dbInfo == null)
{
return;
}

options.ProjectPath = project.FullPath;

if (!await LoadDataBaseObjectsAsync(options))
{
await VS.StatusBar.ClearAsync();
return;
}

await GenerateScriptAsync(options, dbInfo.ConnectionString);
}
catch (AggregateException ae)
{
foreach (var innerException in ae.Flatten().InnerExceptions)
{
VSHelper.ShowError(innerException.Message);
}
}
catch (Exception exception)
{
VSHelper.ShowError(exception.Message);
}
finally
{
await VS.StatusBar.ClearAsync();
}
}

private static async Task GenerateScriptAsync(DataApiBuilderOptions options, string connectionString)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

await VS.StatusBar.ShowProgressAsync("Getting seed data", 1, 2);

var revEngRunner = new ProcessLauncher();

var parts = options.Tables.FirstOrDefault()?.Name.Split('.');

if (parts == null || parts.Length != 2)
{
VSHelper.ShowError("No table selected.");
return;
}

var tableName = parts[1];
var schema = parts[0];

var result = await revEngRunner.CreateMergeScriptAsync(options.ProjectPath, connectionString, tableName, schema);

await VS.StatusBar.ShowProgressAsync("Getting seed data", 2, 2);

if (File.Exists(result))
{
await VS.Documents.OpenAsync(result);
}
}

private static async Task<List<TableModel>> GetTablesAsync(string connectionString)
{
var builder = new TableListBuilder(connectionString, DatabaseType.SQLServer, null);

return await builder.GetTableDefinitionsAsync();
}

private static async Task<bool> LoadDataBaseObjectsAsync(DataApiBuilderOptions options)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

IEnumerable<TableModel> predefinedTables = null;

try
{
await VS.StatusBar.StartAnimationAsync(StatusAnimation.Build);

predefinedTables = await GetTablesAsync(options.ConnectionString);

predefinedTables = predefinedTables
.Where(t => t.ObjectType == ObjectType.Table);
}
catch (InvalidOperationException ex)
{
VSHelper.ShowError($"{ex.Message}");
return false;
}
finally
{
await VS.StatusBar.EndAnimationAsync(StatusAnimation.Build);
}

var preselectedTables = new List<SerializationTableModel>();

await VS.StatusBar.ClearAsync();

var ptd = PackageManager.Package.GetView<IPickTablesDialog>()
.AddTables(predefinedTables, new List<Schema>())
.PreselectTables(preselectedTables);

var pickTablesResult = ptd.ShowAndAwaitUserResponse(true);

options.Tables = pickTablesResult.Payload.Objects.ToList();
return pickTablesResult.ClosedByOK;
}

private async Task<(DatabaseConnectionModel DatabaseModel, int FileGenerationMode, bool ImportSettings)> ChooseDataBaseConnectionAsync(DataApiBuilderOptions options)
{
var vsDataHelper = new VsDataHelper();
var databaseList = await vsDataHelper.GetDataConnectionsAsync();

var psd = PackageManager.Package.GetView<IPickServerDatabaseDialog>();

if (databaseList != null && databaseList.Any())
{
psd.PublishConnections(databaseList.Select(m => new DatabaseConnectionModel
{
ConnectionName = m.Value.ConnectionName,
ConnectionString = m.Value.ConnectionString,
DatabaseType = m.Value.DatabaseType,
DataConnection = m.Value.DataConnection,
}));
}

psd.PublishFileGenerationMode(GetCodeGenerationModes());

var pickDataSourceResult = psd.ShowAndAwaitUserResponse(true);
if (!pickDataSourceResult.ClosedByOK)
{
return (null, 0, false);
}

if (pickDataSourceResult.Payload.Connection != null)
{
options.ConnectionString = pickDataSourceResult.Payload.Connection.ConnectionString;
options.DatabaseType = pickDataSourceResult.Payload.Connection.DatabaseType;
}

return (pickDataSourceResult.Payload.Connection,
pickDataSourceResult.Payload.CodeGenerationMode,
pickDataSourceResult.Payload.GetDatabaseOptions);
}

private static async Task<DatabaseConnectionModel> GetDatabaseInfoAsync(DataApiBuilderOptions options)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

var dbInfo = new DatabaseConnectionModel();

if (!string.IsNullOrEmpty(options.ConnectionString))
{
dbInfo.ConnectionString = options.ConnectionString;
dbInfo.DatabaseType = options.DatabaseType;
}

if (dbInfo.DatabaseType == DatabaseType.Undefined)
{
VSHelper.ShowError($"Unsupported provider");
return null;
}

return dbInfo;
}

private static List<CodeGenerationItem> GetCodeGenerationModes()
{
var list = new List<CodeGenerationItem>
{
new CodeGenerationItem { Key = 0, Value = "Seed" },
};
return list;
}
}
}
Loading
Loading