private string GenerateInterface()
        {
            var repoMemberDeclarations = String.Join(Environment.NewLine + "        ",
                                                     _tables.Select(currTable =>
            {
                var pascalTableName = TSqlModelHelper.PascalCase(currTable.Name.Parts[1]);

                var lowerTableName = currTable.Name.Parts[1].ToLower();
                var tableSettings  = GeneratorSettings.TablesSettings.ContainsKey(lowerTableName) ?
                                     GeneratorSettings.TablesSettings[lowerTableName]
                        : GeneratorSettings.GlobalSettings;

                var repoNamespace     = tableSettings.CsRepositorySettings.Namespace;
                var repoInterfaceName = "I" + pascalTableName + "Repo";
                var repoPropertyName  = pascalTableName + "Repo";

                return($"{repoNamespace}.{repoInterfaceName} {repoPropertyName} {{ get; }}");
            })
                                                     );

            string output = $@"
    public interface {_interfaceName} : IDisposable 
    {{

        IDbConnection Connection {{ get; }}
        IDbTransaction Transaction {{ get; }}

        Task<IDbTransaction> OpenTransaction();
        Task<IDbTransaction> OpenTransaction(IsolationLevel level);
        void CommitTransaction(bool disposeTrans = true);
        void RollbackTransaction(bool disposeTrans = true);


        {repoMemberDeclarations}

    }}


";

            return(output);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// If composite pk, need to define a custom type for select by PKList
        /// </summary>
        /// <returns></returns>
        private string PrintPkType()
        {
            if (!TableSettings.GenerateSelectByPkList)
            {
                return(string.Empty);
            }

            var memberDeclarations = String.Join(Environment.NewLine + "        ", TSqlModelHelper.GetPrimaryKeyColumns(Table).Select(col =>
            {
                var colName     = col.Name.Parts[2];
                var memberName  = TSqlModelHelper.PascalCase(col.Name.Parts[2]);
                var colDataType = col.GetColumnSqlDataType(false);


                //Search for custom member type or use the conversion from Sql Types
                var hasCustomMemberType = _settings?.FieldNameCustomTypes?.ContainsKey(colName) ?? false;

                var memberType = hasCustomMemberType ? _settings.FieldNameCustomTypes[colName]
                    : TSqlModelHelper.GetDotNetDataType(colDataType);


                return($"public {memberType} {memberName} {{ get; set; }}");
            }));

            return
                ($@"
/// =================================================================
/// Author: {GeneratorSettings.AuthorName}
/// Description: PK class for the table {Table.Name} 
/// It's bit heavy (a lot of useless types in the DB) but you can
/// use get by PKList even if your pk is a composite one...
/// =================================================================
    public class {TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_PK
    {{ 
        
        {memberDeclarations}

    }}");
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Load the dacpac model
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void ButtonLoadModel_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(DacpacPath))
                {
                    MessageBox.Show("No dacpac file selected.", "Error to load", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                }
                else
                {
                    _loading++;
                    buttonLoadModel.IsEnabled = false;
                    IsEnabled = false;

                    Model = await Task.Run(() => TSqlModelHelper.LoadModel(DacpacPath));

                    LoadTablesFromModel();
                    Roles = Model.GetAllRoles();

                    ucGlobalSettings.InitGlobalSettings();
                    ucGlobalSettings.IsEnabled = true;
                    IsEnabled = true;
                    buttonLoadConfig.IsEnabled = true;
                    buttonSaveConfig.IsEnabled = true;
                    _loading--;

                    MessageBox.Show("Model loaded successfully", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                buttonLoadModel.IsEnabled = true;
            }
        }
        /// <summary>
        /// Print the custom type linked to PKList select
        /// </summary>
        /// <returns></returns>
        private string PrintPKCustomType()
        {
            var pkFieldParams = String.Join(Environment.NewLine + ", ",
                                            _pkColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"[{colName}] {TSqlModelHelper.GetColumnSqlDataType(col)}");
            })
                                            );

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON TYPE::[dbo].[udt{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_PK] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO"));

            string output = $@"
CREATE TYPE [dbo].[udt{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_PK] AS TABLE
(
	{pkFieldParams}
)

GO

{grants}";

            return(output);
        }
        public override string Generate()
        {
            if (!TableSettings.GenerateSelectByPkList && !PreviewMode)
            {
                return(string.Empty);
            }

            _pkColumns = Table.GetPrimaryKeyColumns();

            var innerJoins = String.Join(Environment.NewLine + "        AND ",
                                         _pkColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"INNER JOIN @pk_list [B] ON [A].[{colName}] = [B].[{colName}]");
            })
                                         );

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON OBJECT::[dbo].[usp{ TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_selectByPKList] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO")
                                     );

            string output =
                $@" 
-- =================================================================
-- Author: {GeneratorSettings.AuthorName}
-- Description:	Select By PKList Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_selectByPKList]
(
    @pk_list [dbo].[udt{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_PK] READONLY
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        SELECT [A].*
        FROM {Table.Name} [A]
        {innerJoins}
        
    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END
GO

{grants}

";

            return(output + PrintPKCustomType());
        }
        public override string Generate()
        {
            if (!TableSettings.GenerateBulkInsertSP && !PreviewMode)
            {
                return(string.Empty);
            }

            var allColumns = Table.GetAllColumns();

            //Exclude columns according to settings
            allColumns = _settings.FieldNamesExcluded != null
                ? allColumns.Where(c => !_settings.FieldNamesExcluded.Split(',').Contains(c.Name.Parts[2]))
                : allColumns;

            // Identity columns will appear as output parameters
            var nonIdentityColumns = allColumns.Where(col => !col.GetProperty <bool>(Column.IsIdentity));
            var identityColumns    = allColumns.Where(col => col.GetProperty <bool>(Column.IsIdentity));

            var tableTypeName = $"[dbo].[udt{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}]";

            var insertClause_columns = String.Join(Environment.NewLine + "        , ",
                                                   nonIdentityColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"[{colName}]");
            }));

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON OBJECT::[dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_bulkInsert] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO")
                                     );

            string output =
                $@" 
-- =================================================================
-- Author: {this.GeneratorSettings.AuthorName}
-- Description:	Bulk Insert Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_bulkInsert]
(
@items {tableTypeName} READONLY
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        INSERT INTO {Table.Name}
        SELECT {insertClause_columns}
	    FROM @items

    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END

GO

{grants}

";

            return(output);
        }
        //TODO see if it's ok to use Dot net type or if we need to use true System.Data.SqlTypes to create the table type
        //that will be injected for bulk insert
        /// <summary>
        /// Table type template for bulkinsert
        /// </summary>
        /// <returns></returns>
        private string PrintTableTypeForBulkInsert()
        {
            var removeIdentityColumns = _allColumns.Where(col => !col.GetProperty <bool>(Column.IsIdentity));

            // Hint: 'addRows' will be filled in addColumns
            string addRows = String.Join(Environment.NewLine + "                    ",
                                         removeIdentityColumns.Select(c =>
            {
                var colName       = c.Name.Parts[2];
                var colIsNullable = c.IsColumnNullable();
                var colSqlType    = TSqlModelHelper.GetDotNetDataType_SystemDataSqlTypes(TSqlModelHelper.GetColumnSqlDataType(c, false));

                // TODO: Better check if column type in settings is an enum
                var forceIntForEnum = colSqlType == "SqlInt32" ? "(int)" : string.Empty;

                return(!colIsNullable || colSqlType == "SqlString" || colSqlType == "SqlBinary"
                        ? $@"row[""{colName}""] = new {colSqlType}({forceIntForEnum}curObj.{TSqlModelHelper.PascalCase(colName)});"
                        : $@"row[""{colName}""] = curObj.{TSqlModelHelper.PascalCase(colName)} == null ? "
                       + $@"{colSqlType}.Null"
                       + $@" : new {colSqlType}({forceIntForEnum}curObj.{TSqlModelHelper.PascalCase(colName)}.Value);");
            })
                                         );

            string addColumns = String.Join(Environment.NewLine + "            ",
                                            removeIdentityColumns.Select(c =>
            {
                var colName    = c.Name.Parts[2];
                var colSqlType = TSqlModelHelper.GetDotNetDataType_SystemDataSqlTypes(TSqlModelHelper.GetColumnSqlDataType(c, false));
                return($@"dt.Columns.Add(""{colName}"", typeof({colSqlType}));");
            })
                                            );

            string output = $@"
        /// <summary>
        /// Create special db table for bulk insert
        /// </summary>
        private object Create{_entityClassName}DataTable(IEnumerable<{_entityClassFullName}> {_entityClassName}List)
        {{
            DataTable dt = new DataTable();
            {addColumns}

            if ({_entityClassName}List != null)
                foreach (var curObj in {_entityClassName}List)
                {{
                    DataRow row = dt.NewRow();
                    {addRows}

                    dt.Rows.Add(row);
                }}

            return dt.AsTableValuedParameter();

        }}";

            return(output);
        }
        //TODO to be tested with composite pk and with Non-Identity PK --- And in general
        //TODO see if it's ok to not specify the db type and only the ouput direction
        /// <summary>
        /// Insert template
        /// </summary>
        /// <returns></returns>
        private string PrintInsertMethod()
        {
            var paramName = FirstCharacterToLower(_entityClassName);

            //Exclude de PK identity field to put "Direction Output" in Dapper params
            bool isOneColumnIdentity = _pkColumns.Count() == 1 && TSqlModelHelper.IsColumnIdentity(_pkColumns.ToList()[0]);
            var  normalColumns       = isOneColumnIdentity ? _allColumns.Except(_pkColumns) : _allColumns;

            string returnType = isOneColumnIdentity
                ? TSqlModelHelper.GetDotNetDataType(TSqlModelHelper.GetColumnSqlDataType(_pkColumns.ToArray()[0]))
                : "bool"; // return bool if insert ok  => we cannot return the new Id generated by Identity

            //If the PK is one identity field + one another field, we are f...
            string returnStatement = (returnType == "bool")
                ? "return true;"
                : $@"return p.Get<{returnType}> (""@{_pkColumns.ToArray()[0].Name.Parts[2]}"");";

            string spPkParams = isOneColumnIdentity
                ? String.Join(Environment.NewLine + "            ",
                              _pkColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($@"p.Add(""@{colName}"", dbType:{TSqlModelHelper.GetDotNetDataType_SystemDataDbTypes(TSqlModelHelper.GetColumnSqlDataType(col,false))}, direction: ParameterDirection.Output);");
            }))
                : string.Empty; // no identity PK

            //Excluded columns in the SP
            var tmpColumns = TableSettings.SqlInsertSettings.FieldNamesExcluded != null
                ? normalColumns.Where(c => !TableSettings.SqlInsertSettings.FieldNamesExcluded.Split(',').Contains(c.Name.Parts[2]))
                : normalColumns;

            string spNormalParams = String.Join(Environment.NewLine + "            ",
                                                tmpColumns.Select(col =>
            {
                var colName    = col.Name.Parts[2];
                var entityProp = TSqlModelHelper.PascalCase(colName);
                return($@"p.Add(""@{colName}"", {paramName}.{entityProp});");
            }));



            string output = $@"
        /// <summary>
        /// Insert
        /// </summary>
        public async  Task<{returnType}> Insert({_entityClassFullName} {paramName})
        {{
            var p = new DynamicParameters();
            {spPkParams}
            {spNormalParams}

            _ = await _dbContext.Connection.ExecuteAsync
                (""usp{_entityClassName}_insert"", p, commandType: CommandType.StoredProcedure, transaction: _dbContext.Transaction);
            
            {returnStatement}
        }}";

            return(output);
        }
        /// <summary>
        /// Loop on each uk to generate the output
        /// </summary>
        /// <returns></returns>
        private IEnumerable <string> GenerateForEachUk()
        {
            var uks = Table.GetUniqueKeysWithColumns();

            foreach (var ukColumns in uks)
            {
                var inputParamDeclarations = String.Join(Environment.NewLine + ", ",
                                                         ukColumns.Select(col =>
                {
                    var colName     = col.Name.Parts[2];
                    var colDataType = col.GetColumnSqlDataType();
                    return($"@{colName} {colDataType}");
                })
                                                         );

                var whereClause_conditions = String.Join(Environment.NewLine + "        AND ",
                                                         ukColumns.Select(col =>
                {
                    var colName = col.Name.Parts[2];
                    return($"[{colName}] = @{colName}");
                })
                                                         );

                var ukFieldNames = String.Join("And",
                                               ukColumns.Select(col =>
                {
                    var colName = col.Name.Parts[2];
                    return($"{TSqlModelHelper.PascalCase(colName)}");
                })
                                               );

                var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                         _settings.GrantExecuteToRoles.Select(roleName =>
                                                                              "GRANT EXECUTE" + Environment.NewLine
                                                                              + $"ON OBJECT::[dbo].[usp{ TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_selectBy{ukFieldNames}] TO [{roleName}] AS [dbo];"
                                                                              + Environment.NewLine + "GO")
                                         );

                string output =
                    $@" 
-- =================================================================
-- Author: {GeneratorSettings.AuthorName}
-- Description:	Select By UK Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_selectBy{ukFieldNames}]
(
{inputParamDeclarations}
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        SELECT * FROM {Table.Name}
        WHERE {whereClause_conditions}
        
    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END
GO

{grants}

";

                yield return(output);
            }
        }
Ejemplo n.º 10
0
        public override string Generate()
        {
            if (!TableSettings.GenerateEntities && !PreviewMode)
            {
                return(string.Empty);
            }

            var allColumns = Table.GetAllColumns();
            var pkColumns  = TSqlModelHelper.GetPrimaryKeyColumns(Table);

            // ICloneable interface
            var iCloneableFuncStr = "public object Clone()" + Environment.NewLine +
                                    "        {" + Environment.NewLine +
                                    "           return this.MemberwiseClone();" + Environment.NewLine +
                                    "        }";

            var iCloneable       = _settings.ImplementICloneable ? " : System.ICloneable" : null;
            var iCloneableMethod = _settings.ImplementICloneable ? iCloneableFuncStr : null;

            // Custom interface names
            string interfaceNames = "";

            if (!string.IsNullOrEmpty(_settings.ImplementCustomInterfaceNames))
            {
                interfaceNames = (_settings.ImplementICloneable)
                    ? ", " + _settings.ImplementCustomInterfaceNames
                    : " : " + _settings.ImplementCustomInterfaceNames;
            }

            var memberDeclarations = String.Join(Environment.NewLine + "        ", allColumns.Select(col =>
            {
                var colName     = col.Name.Parts[2];
                var memberName  = TSqlModelHelper.PascalCase(col.Name.Parts[2]);
                var colDataType = col.GetColumnSqlDataType(false);
                var isNullable  = col.IsColumnNullable();
                bool isPk       = (pkColumns.SingleOrDefault(c => c.Name.Parts[2] == colName) != null) ? true : false;

                //Search for custom member type or use the conversion from Sql Types
                var hasCustomMemberType = _settings?.FieldNameCustomTypes?.ContainsKey(colName) ?? false;

                var memberType = hasCustomMemberType ? _settings.FieldNameCustomTypes[colName]
                    : TSqlModelHelper.GetDotNetDataType(colDataType, isNullable);

                //Decorators
                var decorators = "";

                //String length
                if (_settings.StandardStringLengthDecorator)
                {
                    if (memberType == "string")
                    {
                        var colLen = col.GetProperty <int>(Column.Length);
                        if (colLen > 0)
                        {
                            decorators += $"[System.ComponentModel.DataAnnotations.StringLength({colLen})]"
                                          + Environment.NewLine + "        ";
                        }
                    }
                }

                // TODO : I don't think the condition is correct, check this with fab
                //Required
                if (_settings.StandardRequiredDecorator)
                {
                    if (!isNullable && !isPk)
                    {
                        decorators += $"[System.ComponentModel.DataAnnotations.Required]"
                                      + Environment.NewLine + "        ";
                    }
                }

                //Json ignore
                if (_settings.StandardJsonIgnoreDecorator)
                {
                    var colFound = _settings.FieldNamesWithJsonIgnoreDecorator
                                   .Split(',').Any(c => c == colName);

                    if (colFound)
                    {
                        decorators += $"[Newtonsoft.Json.JsonIgnore]"
                                      + Environment.NewLine + "        ";
                    }
                }

                //Custom field decorator
                if (_settings.FieldNameCustomDecorators != null && _settings.FieldNameCustomDecorators.Count > 0)
                {
                    if (_settings.FieldNameCustomDecorators.TryGetValue(colName, out string customDecorator))
                    {
                        decorators += customDecorator
                                      + Environment.NewLine + "        ";
                    }
                }

                return($"{decorators}public {memberType} {memberName} {{ get; set; }}" + Environment.NewLine);
            }));

            string pkType = PrintPkType();
            string output =
                $@" 
namespace { _settings.Namespace } {{

{pkType}    

/// =================================================================
/// Author: {GeneratorSettings.AuthorName}
/// Description: Entity class for the table {Table.Name} 
/// =================================================================

    public class {TSqlModelHelper.PascalCase(Table.Name.Parts[1])}{iCloneable}{interfaceNames}
    {{ 
        
        {memberDeclarations}

        {iCloneableMethod}

    }}
}}

";

            return(output);
        }
        public override string Generate()
        {
            if (!TableSettings.GenerateBulkUpdateSP && !PreviewMode)
            {
                return(string.Empty);
            }

            var allColumns = Table.GetAllColumns();

            //Exclude columns according to settings
            allColumns = _settings.FieldNamesExcluded != null
                ? allColumns.Where(c => !_settings.FieldNamesExcluded.Split(',').Contains(c.Name.Parts[2]))
                : allColumns;

            // Identity columns will appear as output parameters
            var nonIdentityColumns = allColumns.Where(col => !col.GetProperty <bool>(Column.IsIdentity));
            var identityColumns    = allColumns.Where(col => col.GetProperty <bool>(Column.IsIdentity));
            var pkColumns          = Table.GetPrimaryKeyColumns();

            var tableTypeName = $"[dbo].[udt{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}]";

            var inputParamDeclarations = String.Join(Environment.NewLine + ", ",
                                                     allColumns.Select(col =>
            {
                var colName     = col.Name.Parts[2];
                var colDataType = col.GetColumnSqlDataType();
                return($"@{colName} {colDataType}");
            })
                                                     );

            var updateClause_setStatements = String.Join(Environment.NewLine + "        , ", nonIdentityColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"a.[{colName}] = i.[{colName}]");
            }));

            //var whereClause_conditions = String.Join(" AND ", pkColumns.Select(col =>
            //{
            //    var colName = col.Name.Parts[2];
            //    return $"[{colName}] = @{colName}";
            //}));

            //Only support one field PKS for the moment
            var colNameStr = pkColumns.First().Name.Parts[2];
            var joinClause = $"INNER JOIN @items i ON " + $"a.[{colNameStr}] = i.{colNameStr}";

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON OBJECT::[dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_bulkUpdate] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO")
                                     );

            string output =
                $@" 
-- =================================================================
-- Author: {this.GeneratorSettings.AuthorName}
-- Description:	Bulk Update Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_bulkUpdate]
(
@items {tableTypeName} READONLY
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        UPDATE a
        SET 
        {updateClause_setStatements}
        FROM {Table.Name} a
        {joinClause}

    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END

GO

{grants}

";

            return(output);
        }
Ejemplo n.º 12
0
        public override string Generate()
        {
            if (!TableSettings.GenerateDeleteSP && !PreviewMode)
            {
                return(string.Empty);
            }

            var pkColumns = Table.GetPrimaryKeyColumns();

            var inputParamDeclarations = String.Join(Environment.NewLine + ", ", pkColumns.Select(col =>
            {
                var colName     = col.Name.Parts[2];
                var colDataType = col.GetColumnSqlDataType();
                return($"@{colName} {colDataType}");
            }));

            var whereClause_conditions = String.Join(" AND ", pkColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"[{colName}] = @{colName}");
            }));

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON OBJECT::[dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_delete] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO")
                                     );

            string output =
                $@" 
-- =================================================================
-- Author: {GeneratorSettings.AuthorName}
-- Description:	Delete Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_delete]
(
{inputParamDeclarations}
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        DELETE FROM {Table.Name}
	    WHERE {whereClause_conditions}

    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END

GO

{grants}

";

            return(output);
        }
        private string GenerateClass()
        {
            var repoMemberDefinitions = String.Join(Environment.NewLine,
                                                    _tables.Select(currTable =>
            {
                var pascalTableName = TSqlModelHelper.PascalCase(currTable.Name.Parts[1]);

                var lowerTableName = currTable.Name.Parts[1].ToLower();
                var tableSettings  = GeneratorSettings.TablesSettings.ContainsKey(lowerTableName) ?
                                     GeneratorSettings.TablesSettings[lowerTableName]
                        : GeneratorSettings.GlobalSettings;

                var repoNamespace          = tableSettings.CsRepositorySettings.Namespace;
                var repoInterfaceName      = "I" + pascalTableName + "Repo";
                var repoClassName          = pascalTableName + "Repo";
                var repoPropertyName       = pascalTableName + "Repo";
                var repoProtectedFieldName = $"_{FirstCharacterToLower(repoPropertyName)}";

                return($@"
        protected {repoNamespace}.{repoInterfaceName} {repoProtectedFieldName};
        public {repoNamespace}.{repoInterfaceName} {repoPropertyName} {{
            get {{
                if ({repoProtectedFieldName} == null) 
                    {repoProtectedFieldName} = new {repoNamespace}.{repoClassName}(this);
                return {repoProtectedFieldName};
            }}
        }}
");
            })
                                                    );

            string output = $@"

    /// <summary>
    ///Interface for {_settings.ClassName}Factory
    /// </summary>
    public interface {_interfaceName}Factory
    {{
        {_settings.ClassName} Create();
    }}

    /// <summary>
    /// Used when the DBcontext itself is not suffisent to manage its lifecycle 
    /// Ex in WPF app you need to dispose the DBContexts to allow connection pooling and to be thread safe
    /// Very simple implementation = with only one DB connection (can be extended to support multiple DB con)
    /// </summary>
    public class {_settings.ClassName}Factory : {_interfaceName}Factory
    {{
        private readonly string _conString;
        public {_settings.ClassName}Factory(string dbConnectionString)
        {{
            _conString = dbConnectionString;
        }}

        public {_settings.ClassName} Create()
        {{
            return new {_settings.ClassName}(_conString);
        }}
    }}

    public class {_settings.ClassName} : {_interfaceName}
    {{


        protected readonly IConfiguration _config;
        protected readonly IHostEnvironment _env;

        
        protected IDbConnection _cn = null;
        public IDbConnection Connection {{
            get => _cn;
        }}

        
        protected IDbTransaction _trans = null;
        public IDbTransaction Transaction {{ 
            get => _trans;
        }}


        {repoMemberDefinitions}


        /// <summary>
        /// Main constructor, inject standard config : Default connection string
        /// Need to be reviewed to be more generic (choose the connection string to inject)
        /// </summary>
        public {_settings.ClassName}(IConfiguration config, IHostEnvironment env)
        {{
            _config = config;
            _env = env;
            DefaultTypeMap.MatchNamesWithUnderscores = true;
            _cn = new SqlConnection(_config.GetConnectionString(""{_settings.ConnectionStringName}""));
        }}

        /// <summary>
        /// Main constructor, inject standard config : Default connection string
        /// Pass the connection string directly (in case of usage with WPF or dekstop app, can be heavy to always inject)
        /// </summary>
        public {_settings.ClassName}(string connectionString)
        {{
            DefaultTypeMap.MatchNamesWithUnderscores = true;
            _cn = new SqlConnection(connectionString);
        }}
        

        /// <summary>
        /// Open a transaction
        /// </summary>
        public async Task<IDbTransaction> OpenTransaction()
        {{
            if(_trans != null)
                throw new Exception(""A transaction is already open, you need to use a new {_settings.ClassName} for parallel job."");

            if (_cn.State == ConnectionState.Closed)
            {{
                if (!(_cn is DbConnection))
                    throw new Exception(""Connection object does not support OpenAsync."");
                
                await (_cn as DbConnection).OpenAsync();
            }}

            _trans = _cn.BeginTransaction();

            return _trans;
        }}


        /// <summary>
        /// Open a transaction with a specified isolation level
        /// </summary>
        public async Task<IDbTransaction> OpenTransaction(IsolationLevel level)
        {{
            if(_trans != null)
                throw new Exception(""A transaction is already open, you need to use a new {_settings.ClassName} for parallel job."");

            if (_cn.State == ConnectionState.Closed)
            {{
                if (!(_cn is DbConnection))
                    throw new Exception(""Connection object does not support OpenAsync."");
                
                await (_cn as DbConnection).OpenAsync();
            }}

            _trans = _cn.BeginTransaction(level);

            return _trans;
        }}


        /// <summary>
        /// Commit the current transaction, and optionally dispose all resources related to the transaction.
        /// </summary>
        public void CommitTransaction(bool disposeTrans = true)
        {{
            if  (_trans == null)
                throw new Exception(""DB Transaction is not present."");

            _trans.Commit();
            if (disposeTrans) _trans.Dispose();
            if (disposeTrans) _trans = null;
        }}

        /// <summary>
        /// Rollback the transaction and all the operations linked to it, and optionally dispose all resources related to the transaction.
        /// </summary>
        public void RollbackTransaction(bool disposeTrans = true)
        {{
            if  (_trans == null)
                throw new Exception(""DB Transaction is not present."");

            _trans.Rollback();
            if (disposeTrans) _trans.Dispose();
            if (disposeTrans) _trans = null;
        }}

        /// <summary>
        /// Will be call at the end of the service (ex : transient service in api net core)
        /// </summary>
        public void Dispose()
        {{
            _trans?.Dispose();
            _cn?.Close();
            _cn?.Dispose();
        }}


    }}

";

            return(output);
        }
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private string PrintPKTypeForSelectByPKList()
        {
            string addColumns = String.Join(Environment.NewLine + "            ",
                                            _pkColumns.Select(c =>
            {
                var colName    = c.Name.Parts[2];
                var colSqlType = TSqlModelHelper.GetDotNetDataType_SystemDataSqlTypes(TSqlModelHelper.GetColumnSqlDataType(c, false));

                return($@"      dt.Columns.Add(""{colName}"", typeof({colSqlType}));");
            }));

            string addRows = String.Join(Environment.NewLine + "            ",
                                         _pkColumns.Select(c =>
            {
                var colName    = c.Name.Parts[2];
                var colSqlType = TSqlModelHelper.GetDotNetDataType_SystemDataSqlTypes(TSqlModelHelper.GetColumnSqlDataType(c, false));

                // TODO: Better check if column type in settings is an enum
                var forceIntForEnum = colSqlType == "SqlInt32" ? "(int)" : string.Empty;

                return($@"row[""{colName}""] = new {colSqlType}({forceIntForEnum}curObj.{TSqlModelHelper.PascalCase(colName)});");
            }));

            string output = $@"
        /// <summary>
        /// Create special db table for select by PK List
        /// </summary>
        private object Create{_entityClassName}PKDataTable(IEnumerable<{_entityClassFullName}_PK> pkList)
        {{
            DataTable dt = new DataTable();
            {addColumns}

            if (pkList != null)
                foreach (var curObj in pkList)
                {{
                    DataRow row = dt.NewRow();
                    {addRows}
                    dt.Rows.Add(row);
                }}

            return dt.AsTableValuedParameter();

        }}";

            return(output);
        }
        public override string Generate()
        {
            if (!TableSettings.GenerateInsertSP && !PreviewMode)
            {
                return(string.Empty);
            }

            var allColumns         = Table.GetAllColumns();
            var nonIdentityColumns = allColumns.Where(col => !col.GetProperty <bool>(Column.IsIdentity));
            var identityColumns    = allColumns.Where(col => col.GetProperty <bool>(Column.IsIdentity));

            // Join output & input param declarations
            var paramDeclarations = String.Join(Environment.NewLine + ", ",
                                                identityColumns.Select(col =>
            {
                var colName     = col.Name.Parts[2];
                var colDataType = col.GetColumnSqlDataType();
                return($"@{colName} {colDataType} OUT");
            })
                                                .Concat(
                                                    nonIdentityColumns.Select(col =>
            {
                var colName     = col.Name.Parts[2];
                var colDataType = col.GetColumnSqlDataType();
                return($"@{colName} {colDataType}");
            }))
                                                );

            var tmpNonIdentiyColumns = _settings.FieldNamesExcluded != null
                ? nonIdentityColumns.Where(c => !_settings.FieldNamesExcluded.Split(',').Contains(c.Name.Parts[2]))
                : nonIdentityColumns;

            var insertClause_columns = String.Join(Environment.NewLine + "        , ",
                                                   tmpNonIdentiyColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"[{colName}]");
            }));

            var insertClause_values = String.Join(Environment.NewLine + "        , ",
                                                  tmpNonIdentiyColumns.Select(col =>
            {
                var colName = col.Name.Parts[2];
                return($"@{colName}");
            })
                                                  );

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON OBJECT::[dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_insert] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO")
                                     );

            string output =
                $@" 
-- =================================================================
-- Author: {GeneratorSettings.AuthorName}
-- Description:	Insert Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_insert]
(
{paramDeclarations}
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        INSERT INTO {Table.Name}
        (
        {insertClause_columns}
        )
	    VALUES 
        (
        {insertClause_values}
        )

        SET @id = SCOPE_IDENTITY()

    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END

GO

{grants}

";

            return(output);
        }
        public override string Generate()
        {
            if (!TableSettings.GenerateSelectAllSP && !PreviewMode)
            {
                return(string.Empty);
            }

            var grants = String.Join(Environment.NewLine + Environment.NewLine,
                                     _settings.GrantExecuteToRoles.Select(roleName =>
                                                                          "GRANT EXECUTE" + Environment.NewLine
                                                                          + $"ON OBJECT::[dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_selectAll] TO [{roleName}] AS [dbo];"
                                                                          + Environment.NewLine + "GO")
                                     );

            string output =
                $@" 
-- =================================================================
-- Author: {GeneratorSettings.AuthorName}
-- Description:	Select All Procedure for the table {Table.Name} 
-- =================================================================

CREATE PROCEDURE [dbo].[usp{TSqlModelHelper.PascalCase(Table.Name.Parts[1])}_selectAll]
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE
        @strErrorMessage NVARCHAR(4000),
        @intErrorSeverity INT,
        @intErrorState INT,
        @intErrorLine INT;

    BEGIN TRY
    
        SELECT * FROM {Table.Name}
        
    END TRY
    BEGIN CATCH
        SELECT
            @strErrorMessage = ERROR_MESSAGE()
                    + ' Line:'
                    + CONVERT(VARCHAR(5), ERROR_LINE()),
            @intErrorSeverity = ERROR_SEVERITY(),
            @intErrorState = ERROR_STATE();
        RAISERROR(
                @strErrorMessage,   -- Message text.
                @intErrorSeverity,  -- Severity.
                @intErrorState      -- State.
        );
    END CATCH;
END

GO

{grants}

";

            return(output);
        }