aspnetcore/src/Microsoft.Extensions.Cachin.../Program.cs

174 lines
6.0 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.Extensions.Caching.SqlConfig.Tools
{
public class Program
{
private string _connectionString = null;
private string _schemaName = null;
private string _tableName = null;
private readonly IConsole _console;
public Program(IConsole console)
{
Ensure.NotNull(console, nameof(console));
_console = console;
}
public static int Main(string[] args)
{
return new Program(PhysicalConsole.Singleton).Run(args);
}
public int Run(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);
try
{
var app = new CommandLineApplication
{
Name = "dotnet sql-cache",
FullName = "SQL Server Cache Command Line Tool",
Description =
"Creates table and indexes in Microsoft SQL Server database to be used for distributed caching",
};
app.HelpOption();
app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly);
var verbose = app.VerboseOption();
app.Command("create", command =>
{
command.Description = app.Description;
var connectionStringArg = command.Argument(
"[connectionString]", "The connection string to connect to the database.");
var schemaNameArg = command.Argument(
"[schemaName]", "Name of the table schema.");
var tableNameArg = command.Argument(
"[tableName]", "Name of the table to be created.");
command.HelpOption();
command.OnExecute(() =>
{
var reporter = CreateReporter(verbose.HasValue());
if (string.IsNullOrEmpty(connectionStringArg.Value)
|| string.IsNullOrEmpty(schemaNameArg.Value)
|| string.IsNullOrEmpty(tableNameArg.Value))
{
reporter.Error("Invalid input");
app.ShowHelp();
return 2;
}
_connectionString = connectionStringArg.Value;
_schemaName = schemaNameArg.Value;
_tableName = tableNameArg.Value;
return CreateTableAndIndexes(reporter);
});
});
// Show help information if no subcommand/option was specified.
app.OnExecute(() =>
{
app.ShowHelp();
return 2;
});
return app.Execute(args);
}
catch (Exception exception)
{
CreateReporter(verbose: false).Error($"An error occurred. {exception.Message}");
return 1;
}
}
private IReporter CreateReporter(bool verbose)
=> new ConsoleReporter(_console, verbose, quiet: false);
private int CreateTableAndIndexes(IReporter reporter)
{
ValidateConnectionString();
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
var sqlQueries = new SqlQueries(_schemaName, _tableName);
var command = new SqlCommand(sqlQueries.TableInfo, connection);
using (var reader = command.ExecuteReader(CommandBehavior.SingleRow))
{
if (reader.Read())
{
reporter.Warn(
$"Table with schema '{_schemaName}' and name '{_tableName}' already exists. " +
"Provide a different table name and try again.");
return 1;
}
}
using (var transaction = connection.BeginTransaction())
{
try
{
command = new SqlCommand(sqlQueries.CreateTable, connection, transaction);
reporter.Verbose($"Executing {command.CommandText}");
command.ExecuteNonQuery();
command = new SqlCommand(
sqlQueries.CreateNonClusteredIndexOnExpirationTime,
connection,
transaction);
reporter.Verbose($"Executing {command.CommandText}");
command.ExecuteNonQuery();
transaction.Commit();
reporter.Output("Table and index were created successfully.");
}
catch (Exception ex)
{
reporter.Error(
$"An error occurred while trying to create the table and index. {ex.Message}");
transaction.Rollback();
return 1;
}
}
}
return 0;
}
private void ValidateConnectionString()
{
try
{
new SqlConnectionStringBuilder(_connectionString);
}
catch (Exception ex)
{
throw new ArgumentException(
$"Invalid SQL Server connection string '{_connectionString}'. {ex.Message}", ex);
}
}
}
}