예제 #1
0
        internal async Task <(SyncTable SyncTable, IEnumerable <DbRelationDefinition> Relations)> InternalGetTableSchemaAsync(
            SyncContext context, SyncSetup setup, SetupTable setupTable, DbConnection connection, DbTransaction transaction,
            CancellationToken cancellationToken, IProgress <ProgressArgs> progress)
        {
            // ensure table is compliante with name / schema with provider
            var syncTable = await this.Provider.GetDatabaseBuilder().EnsureTableAsync(setupTable.TableName, setupTable.SchemaName, connection, transaction);

            var tableBuilder = this.GetTableBuilder(syncTable, setup);

            var exists = await InternalExistsTableAsync(context, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (!exists)
            {
                throw new MissingTableException(string.IsNullOrEmpty(setupTable.SchemaName) ? setupTable.TableName : setupTable.SchemaName + "." + setupTable.TableName);
            }

            // get columns list
            var lstColumns = await tableBuilder.GetColumnsAsync(connection, transaction).ConfigureAwait(false);

            // Validate the column list and get the dmTable configuration object.
            this.FillSyncTableWithColumns(setupTable, syncTable, lstColumns);

            // Check primary Keys
            await SetPrimaryKeysAsync(syncTable, tableBuilder, connection, transaction).ConfigureAwait(false);

            // get all relations
            var tableRelations = await tableBuilder.GetRelationsAsync(connection, transaction).ConfigureAwait(false);

            return(syncTable, tableRelations);
        }
        /// <summary>
        /// Create a trigger
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to create the trigger</param>
        /// <param name="triggerType">Trigger type (Insert, Delete, Update)</param>
        /// <param name="overwrite">If true, drop the existing trriger then create again</param>
        public Task <bool> CreateTriggerAsync(SetupTable table, DbTriggerType triggerType, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) =>
        {
            bool hasBeenCreated = false;

            var schema = await this.InternalGetSchemaAsync(ctx, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            var schemaTable = schema.Tables[table.TableName, table.SchemaName];

            if (schemaTable == null)
            {
                throw new MissingTableException(table.GetFullName());
            }

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var exists = await InternalExistsTriggerAsync(ctx, tableBuilder, triggerType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            // should create only if not exists OR if overwrite has been set
            var shouldCreate = !exists || overwrite;

            if (shouldCreate)
            {
                // Drop trigger if already exists
                if (exists && overwrite)
                {
                    await InternalDropTriggerAsync(ctx, tableBuilder, triggerType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);
                }

                hasBeenCreated = await InternalCreateTriggerAsync(ctx, tableBuilder, triggerType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);
            }

            return(hasBeenCreated);
        }, connection, transaction, cancellationToken);
예제 #3
0
        /// <summary>
        /// Read the schema stored from the orchestrator database, through the provider.
        /// </summary>
        /// <returns>Schema containing tables, columns, relations, primary keys</returns>
        public virtual Task <SyncTable> GetTableSchemaAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.SchemaReading, async(ctx, connection, transaction) =>
        {
            var(schemaTable, _) = await this.InternalGetTableSchemaAsync(ctx, this.Setup, table, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (schemaTable == null)
            {
                throw new MissingTableException(table.GetFullName());
            }

            // Create a temporary SyncSet for attaching to the schemaTable
            var schema = new SyncSet();

            // Add this table to schema
            schema.Tables.Add(schemaTable);

            schema.EnsureSchema();

            // copy filters from setup
            foreach (var filter in this.Setup.Filters)
            {
                schema.Filters.Add(filter);
            }

            return(schemaTable);
        }, connection, transaction, cancellationToken);
        /// <summary>
        /// Deprovision the orchestrator database based on the Setup table argument, and the provision enumeration
        /// </summary>
        /// <param name="provision">Provision enumeration to determine which components to deprovision</param>
        public virtual Task DeprovisionAsync(SetupTable table, SyncProvision provision, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        {
            var setup = new SyncSetup();

            setup.Tables.Add(table);

            // using a fake SyncTable based on oldSetup, since we don't need columns, but we need to have the filters
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            // Create a temporary SyncSet for attaching to the schemaTable
            var tmpSchema = new SyncSet();

            // Add this table to schema
            tmpSchema.Tables.Add(schemaTable);

            tmpSchema.EnsureSchema();

            // copy filters from old setup
            foreach (var filter in this.Setup.Filters)
            {
                tmpSchema.Filters.Add(filter);
            }


            return(this.DeprovisionAsync(tmpSchema, provision, connection, transaction, cancellationToken, progress));
        }
        /// <summary>
        /// Drop a table
        /// </summary>
        /// <param name="table">A table from your Setup instance you want to drop</param>
        public Task <bool> DropTableAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Deprovisioning, async(ctx, connection, transaction) =>
        {
            var hasBeenDropped = false;

            var schema = await this.InternalGetSchemaAsync(ctx, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            var schemaTable = schema.Tables[table.TableName, table.SchemaName];

            if (schemaTable == null)
            {
                throw new MissingTableException(table.GetFullName());
            }

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var exists = await InternalExistsTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (exists)
            {
                hasBeenDropped = await InternalDropTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);
            }

            return(hasBeenDropped);
        }, connection, transaction, cancellationToken);
예제 #6
0
        /// <summary>
        /// Drop all Stored Procedures
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to drop all the Stored Procedures</param>
        public Task <bool> DropStoredProceduresAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Deprovisioning, async(ctx, connection, transaction) =>
        {
            var hasDroppedAtLeastOneStoredProcedure = false;

            // using a fake SyncTable based on SetupTable, since we don't need columns
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            // Create a temporary SyncSet for attaching to the schemaTable
            var schema = new SyncSet();

            // Add this table to schema
            schema.Tables.Add(schemaTable);

            schema.EnsureSchema();

            // copy filters from setup
            foreach (var filter in this.Setup.Filters)
            {
                schema.Filters.Add(filter);
            }

            // using a fake SyncTable based on SetupTable, since we don't need columns
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            // check bulk before
            hasDroppedAtLeastOneStoredProcedure = await InternalDropStoredProceduresAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            // Removing cached commands
            var syncAdapter = this.GetSyncAdapter(schemaTable, this.Setup);
            syncAdapter.RemoveCommands();

            return(hasDroppedAtLeastOneStoredProcedure);
        }, connection, transaction, cancellationToken);
예제 #7
0
        /// <summary>
        /// Check if a Stored Procedure exists
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to check if the Stored Procedure exists</param>
        /// <param name="storedProcedureType">StoredProcedure type</param>
        public Task <bool> ExistStoredProcedureAsync(SetupTable table, DbStoredProcedureType storedProcedureType, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.None, async(ctx, connection, transaction) =>
        {
            // using a fake SyncTable based on SetupTable, since we don't need columns
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            // Create a temporary SyncSet for attaching to the schemaTable
            var schema = new SyncSet();

            // Add this table to schema
            schema.Tables.Add(schemaTable);

            schema.EnsureSchema();

            // copy filters from setup
            foreach (var filter in this.Setup.Filters)
            {
                schema.Filters.Add(filter);
            }

            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var exists = await InternalExistsStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            return(exists);
        }, connection, transaction, cancellationToken);
예제 #8
0
        /// <summary>
        /// Deprovision the orchestrator database based on the Setup table argument, and the provision enumeration
        /// </summary>
        /// <param name="provision">Provision enumeration to determine which components to deprovision</param>
        public virtual Task DeprovisionAsync(SetupTable table, SyncProvision provision, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        {
            var setup = new SyncSetup();

            setup.Tables.Add(table);

            return(this.DeprovisionAsync(new SyncSet(setup), provision, cancellationToken, progress));
        }
        /// <summary>
        /// Drop all triggers
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to drop all the triggers</param>
        public Task <bool> DropTriggersAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Deprovisioning, (ctx, connection, transaction) =>
        {
            // Fake sync table without column definitions. Not need for making a drop call
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            return(this.InternalDropTriggersAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress));
        }, connection, transaction, cancellationToken);
예제 #10
0
        /// <summary>
        /// Enabling constraints on one table
        /// </summary>
        public Task <bool> EnableConstraintsAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.None, async(ctx, connection, transaction) =>
        {
            // using a fake SyncTable based on SetupTable, since we don't need columns
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            var syncAdapter = this.GetSyncAdapter(schemaTable, this.Setup);

            await this.InternalEnableConstraintsAsync(ctx, syncAdapter, connection, transaction).ConfigureAwait(false);

            return(true);
        }, connection, transaction, cancellationToken);
        /// <summary>
        /// Check if a trigger exists
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to check if the trigger exists</param>
        /// <param name="triggerType">Trigger type (Insert, Delete, Update)</param>
        public Task <bool> ExistTriggerAsync(SetupTable table, DbTriggerType triggerType, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.None, async(ctx, connection, transaction) =>
        {
            // Fake sync table without column definitions. Not need for making a check exists call
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var exists = await InternalExistsTriggerAsync(ctx, tableBuilder, triggerType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            return(exists);
        }, connection, transaction, cancellationToken);
예제 #12
0
        /// <summary>
        /// Create a Stored Procedure
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to create the Stored Procedure</param>
        /// <param name="storedProcedureType">StoredProcedure type</param>
        /// <param name="overwrite">If true, drop the existing stored procedure then create again</param>
        public Task <bool> CreateStoredProcedureAsync(SetupTable table, DbStoredProcedureType storedProcedureType, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) =>
        {
            bool hasBeenCreated = false;

            var(schemaTable, _) = await this.InternalGetTableSchemaAsync(ctx, this.Setup, table, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (schemaTable == null)
            {
                throw new MissingTableException(table.GetFullName());
            }

            // Create a temporary SyncSet for attaching to the schemaTable
            var schema = new SyncSet();

            // Add this table to schema
            schema.Tables.Add(schemaTable);

            schema.EnsureSchema();

            // copy filters from setup
            foreach (var filter in this.Setup.Filters)
            {
                schema.Filters.Add(filter);
            }

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var exists = await InternalExistsStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            // should create only if not exists OR if overwrite has been set
            var shouldCreate = !exists || overwrite;

            if (shouldCreate)
            {
                // Drop storedProcedure if already exists
                if (exists && overwrite)
                {
                    await InternalDropStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);
                }

                hasBeenCreated = await InternalCreateStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);
            }

            return(hasBeenCreated);
        }, connection, transaction, cancellationToken);
예제 #13
0
        /// <summary>
        /// Create a Stored Procedure
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to create the Stored Procedures</param>
        /// <param name="overwrite">If true, drop the existing Stored Procedures then create them all, again</param>
        public Task <bool> CreateStoredProceduresAsync(SetupTable table, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) =>
        {
            var schema = await this.InternalGetSchemaAsync(ctx, this.Setup, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            var schemaTable = schema.Tables[table.TableName, table.SchemaName];

            if (schemaTable == null)
            {
                throw new MissingTableException(table.GetFullName());
            }

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var r = await InternalCreateStoredProceduresAsync(ctx, overwrite, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            return(r);
        }, connection, transaction, cancellationToken);
        private async Task <(SyncTable SyncTable, IEnumerable <DbRelationDefinition> Relations)> InternalGetTableSchemaAsync
            (SyncContext context, SetupTable setupTable, DbConnection connection, DbTransaction transaction,
            CancellationToken cancellationToken, IProgress <ProgressArgs> progress)
        {
            if (Provider == null)
            {
                throw new MissingProviderException(nameof(InternalGetTableSchemaAsync));
            }

            // ensure table is compliante with name / schema with provider
            var syncTable = await this.Provider.GetDatabaseBuilder().EnsureTableAsync(setupTable.TableName, setupTable.SchemaName, connection, transaction);

            // tmp scope info
            var scopeInfo = this.InternalCreateScopeInfo(context.ScopeName, DbScopeType.Client);

            scopeInfo.Setup = new SyncSetup();
            scopeInfo.Setup.Tables.Add(setupTable);

            var tableBuilder = this.GetTableBuilder(syncTable, scopeInfo);

            bool exists;

            (context, exists) = await InternalExistsTableAsync(scopeInfo, context, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (!exists)
            {
                throw new MissingTableException(setupTable.TableName, setupTable.SchemaName, scopeInfo.Name);
            }

            // get columns list
            var lstColumns = await tableBuilder.GetColumnsAsync(connection, transaction).ConfigureAwait(false);

            // Validate the column list and get the dmTable configuration object.
            this.FillSyncTableWithColumns(setupTable, syncTable, lstColumns);

            // Check primary Keys
            await SetPrimaryKeysAsync(syncTable, tableBuilder, connection, transaction).ConfigureAwait(false);

            // get all relations
            var tableRelations = await tableBuilder.GetRelationsAsync(connection, transaction).ConfigureAwait(false);

            return(syncTable, tableRelations);
        }
        /// <summary>
        /// Dropping a trigger
        /// </summary>
        /// <param name="table">A table from your Setup instance, where you want to drop the trigger</param>
        /// <param name="triggerType">Trigger type (Insert, Delete, Update)</param>
        public Task <bool> DropTriggerAsync(SetupTable table, DbTriggerType triggerType, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        => RunInTransactionAsync(SyncStage.Deprovisioning, async(ctx, connection, transaction) =>
        {
            bool hasBeenDropped = false;

            // Fake sync table without column definitions. Not need for making a drop call
            var schemaTable = new SyncTable(table.TableName, table.SchemaName);

            // Get table builder
            var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup);

            var existsAndCanBeDeleted = await InternalExistsTriggerAsync(ctx, tableBuilder, triggerType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (existsAndCanBeDeleted)
            {
                hasBeenDropped = await InternalDropTriggerAsync(ctx, tableBuilder, triggerType, connection, transaction, cancellationToken, progress).ConfigureAwait(false);
            }

            return(hasBeenDropped);
        }, connection, transaction, cancellationToken);
예제 #16
0
        /// <summary>
        /// Generate the DmTable configuration from a given columns list
        /// Validate that all columns are currently supported by the provider
        /// </summary>
        private void FillSyncTableWithColumns(SetupTable setupTable, SyncTable schemaTable, IEnumerable <SyncColumn> columns)
        {
            schemaTable.OriginalProvider = this.Provider.GetProviderTypeName();
            schemaTable.SyncDirection    = setupTable.SyncDirection;

            var ordinal = 0;

            // Eventually, do not raise exception here, just we don't have any columns
            if (columns == null || columns.Any() == false)
            {
                return;
            }

            // Delete all existing columns
            if (schemaTable.PrimaryKeys.Count > 0)
            {
                schemaTable.PrimaryKeys.Clear();
            }

            if (schemaTable.Columns.Count > 0)
            {
                schemaTable.Columns.Clear();
            }


            IEnumerable <SyncColumn> lstColumns;

            // Validate columns list from setup table if any
            if (setupTable.Columns != null && setupTable.Columns.Count > 1)
            {
                lstColumns = new List <SyncColumn>();

                foreach (var setupColumn in setupTable.Columns)
                {
                    // Check if the columns list contains the column name we specified in the setup
                    var column = columns.FirstOrDefault(c => c.ColumnName.Equals(setupColumn, SyncGlobalization.DataSourceStringComparison));

                    if (column == null)
                    {
                        throw new MissingColumnException(setupColumn, schemaTable.TableName);
                    }
                    else
                    {
                        ((List <SyncColumn>)lstColumns).Add(column);
                    }
                }
            }
            else
            {
                lstColumns = columns;
            }


            foreach (var column in lstColumns.OrderBy(c => c.Ordinal))
            {
                // First of all validate if the column is currently supported
                if (!this.Provider.GetMetadata().IsValid(column))
                {
                    throw new UnsupportedColumnTypeException(column.ColumnName, column.OriginalTypeName, this.Provider.GetProviderTypeName());
                }

                var columnNameLower = column.ColumnName.ToLowerInvariant();
                if (columnNameLower == "sync_scope_name" ||
                    columnNameLower == "scope_timestamp" ||
                    columnNameLower == "scope_is_local" ||
                    columnNameLower == "scope_last_sync" ||
                    columnNameLower == "create_scope_id" ||
                    columnNameLower == "update_scope_id" ||
                    columnNameLower == "create_timestamp" ||
                    columnNameLower == "update_timestamp" ||
                    columnNameLower == "timestamp" ||
                    columnNameLower == "sync_row_is_tombstone" ||
                    columnNameLower == "last_change_datetime" ||
                    columnNameLower == "sync_scope_name" ||
                    columnNameLower == "sync_scope_name"
                    )
                {
                    throw new UnsupportedColumnNameException(column.ColumnName, column.OriginalTypeName, this.Provider.GetProviderTypeName());
                }

                // Validate max length
                column.MaxLength = this.Provider.GetMetadata().ValidateMaxLength(column.OriginalTypeName, column.IsUnsigned, column.IsUnicode, column.MaxLength);

                // Gets the datastore owner dbType (could be SqlDbtype, MySqlDbType, SqliteDbType, NpgsqlDbType & so on ...)
                var datastoreDbType = this.Provider.GetMetadata().ValidateOwnerDbType(column.OriginalTypeName, column.IsUnsigned, column.IsUnicode, column.MaxLength);

                // once we have the datastore type, we can have the managed type
                var columnType = this.Provider.GetMetadata().ValidateType(datastoreDbType);

                // and the DbType
                column.DbType = (int)this.Provider.GetMetadata().ValidateDbType(column.OriginalTypeName, column.IsUnsigned, column.IsUnicode, column.MaxLength);

                // Gets the owner dbtype (SqlDbType, OracleDbType, MySqlDbType, NpsqlDbType & so on ...)
                // Sqlite does not have it's own type, so it's DbType too
                column.OriginalDbType = datastoreDbType.ToString();

                // Validate if column should be readonly
                column.IsReadOnly = this.Provider.GetMetadata().ValidateIsReadonly(column);

                // set position ordinal
                column.Ordinal = ordinal;
                ordinal++;

                // Validate the precision and scale properties
                if (this.Provider.GetMetadata().IsNumericType(column.OriginalTypeName))
                {
                    if (this.Provider.GetMetadata().SupportScale(column.OriginalTypeName))
                    {
                        var(p, s)                 = this.Provider.GetMetadata().ValidatePrecisionAndScale(column);
                        column.Precision          = p;
                        column.PrecisionSpecified = true;
                        column.Scale              = s;
                        column.ScaleSpecified     = true;
                    }
                    else
                    {
                        column.Precision          = this.Provider.GetMetadata().ValidatePrecision(column);
                        column.PrecisionSpecified = true;
                        column.ScaleSpecified     = false;
                    }
                }

                // if setup table has no columns, we add all columns from db
                // otherwise check if columns exist in the data source
                if (setupTable.Columns == null || setupTable.Columns.Count <= 0 || setupTable.Columns.Contains(column.ColumnName))
                {
                    schemaTable.Columns.Add(column);
                }
                // If column does not allow null value and is not compute
                // We will not be able to insert a row, so raise an error
                else if (!column.AllowDBNull && !column.IsCompute && !column.IsReadOnly && string.IsNullOrEmpty(column.DefaultValue))
                {
                    throw new Exception($"Column {column.ColumnName} is not part of your setup. But it seems this columns is mandatory in your data source.");
                }
            }
        }
예제 #17
0
 public MigrationSetupTable(SetupTable table)
 {
     this.SetupTable = table;
 }