예제 #1
0
 protected bool TryGetUpdateCommand(SqlCachedUpdateInsertFormatKey sqlCachedUpdateInsertFormatKey, out SqlCachedUpdateInsertFormatValue sqlCachedUpdateInsertFormatValue)
 {
     return(this.SqlDatabaseContext.formattedUpdateSqlCache.TryGetValue(sqlCachedUpdateInsertFormatKey, out sqlCachedUpdateInsertFormatValue));
 }
예제 #2
0
        protected virtual IDbCommand BuildInsertCommand(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject)
        {
            var        success = false;
            IDbCommand command = null;
            SqlCachedUpdateInsertFormatValue cachedValue;
            bool predicated;

            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;

            var updatedProperties = dataAccessObject.ToObjectInternal().GetChangedPropertiesFlattened(out predicated);

            if (predicated)
            {
                return(BuildInsertCommandForDeflatedPredicated(typeDescriptor, dataAccessObject, updatedProperties));
            }

            var commandKey = new SqlCachedUpdateInsertFormatKey(dataAccessObject.GetType(), updatedProperties, requiresIdentityInsert);

            if (this.TryGetInsertCommand(commandKey, out cachedValue))
            {
                try
                {
                    command             = this.CreateCommand();
                    command.CommandText = cachedValue.formatResult.CommandText;
                    this.FillParameters(command, cachedValue, updatedProperties, null);

                    success = true;

                    return(command);
                }
                finally
                {
                    if (!success)
                    {
                        command?.Dispose();
                    }
                }
            }

            IReadOnlyList <string> returningAutoIncrementColumnNames = null;

            if (dataAccessObject.GetAdvanced().DefinesAnyDirectPropertiesGeneratedOnTheServerSide)
            {
                var propertyDescriptors = typeDescriptor.PersistedPropertiesWithoutBackreferences.Where(c => c.IsPropertyThatIsCreatedOnTheServerSide).ToList();

                returningAutoIncrementColumnNames = propertyDescriptors.Select(c => c.PersistedName).ToReadOnlyCollection();
            }

            var constantPlaceholdersCount = 0;
            var valueIndexesToParameterPlaceholderIndexes = new int[updatedProperties.Count];

            var columnNames = updatedProperties.Select(c => c.PersistedName).ToReadOnlyCollection();

            var valueExpressions = new List <Expression>(updatedProperties.Count);

            foreach (var updated in updatedProperties)
            {
                var value = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));

                if (value.Type != updated.PropertyType)
                {
                    value = Expression.Convert(value, updated.PropertyType);
                }

                valueExpressions.Add(value);
            }

            Expression expression = new SqlInsertIntoExpression(new SqlTableExpression(typeDescriptor.PersistedName), columnNames, returningAutoIncrementColumnNames, valueExpressions, null, requiresIdentityInsert);

            for (var i = 0; i < constantPlaceholdersCount; i++)
            {
                valueIndexesToParameterPlaceholderIndexes[i] = i;
            }

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression);

            try
            {
                command = this.CreateCommand();

                var commandText = result.CommandText;

                command.CommandText = commandText;
                cachedValue         = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result, valueIndexesToParameterPlaceholderIndexes = valueIndexesToParameterPlaceholderIndexes, primaryKeyIndexesToParameterPlaceholderIndexes = null
                };

                if (result.Cacheable)
                {
                    this.CacheInsertCommand(commandKey, cachedValue);
                }

                this.FillParameters(command, cachedValue, updatedProperties, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
예제 #3
0
 protected void CacheUpdateCommand(SqlCachedUpdateInsertFormatKey sqlCachedUpdateInsertFormatKey, SqlCachedUpdateInsertFormatValue sqlCachedUpdateInsertFormatValue)
 {
     this.SqlDatabaseContext.formattedUpdateSqlCache = this.SqlDatabaseContext.formattedUpdateSqlCache.Clone(sqlCachedUpdateInsertFormatKey, sqlCachedUpdateInsertFormatValue, "formattedUpdateSqlCache");
 }
예제 #4
0
        protected IDbCommand BuildInsertCommandForDeflatedPredicated(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject, List <ObjectPropertyValue> updatedProperties)
        {
            var constantPlaceholdersCount = 0;
            var assignments = new List <Expression>();
            var success     = false;

            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;

            var parameter1 = Expression.Parameter(typeDescriptor.Type);

            foreach (var updated in updatedProperties)
            {
                var placeholder = updated.Value as Expression ?? new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));

                if (placeholder.Type != updated.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, updated.PropertyType);
                }

                var m = TypeUtils.GetMethod(() => default(DataAccessObject).SetColumnValue(default(string), default(int)))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(typeDescriptor.Type, updated.PropertyType);

                assignments.Add(Expression.Call(null, m, parameter1, Expression.Constant(updated.PersistedName), placeholder));
            }

            var method = TypeUtils.GetMethod(() => default(IQueryable <DataAccessObject>).InsertHelper(default(Expression <Action <DataAccessObject> >), default(bool)))
                         .GetGenericMethodDefinition()
                         .MakeGenericMethod(typeDescriptor.Type);

            var source     = Expression.Constant(this.DataAccessModel.GetDataAccessObjects(typeDescriptor.Type));
            var selector   = Expression.Lambda(Expression.Block(assignments), parameter1);
            var expression = (Expression)Expression.Call(null, method, source, Expression.Quote(selector), Expression.Constant(requiresIdentityInsert));

            expression = SqlQueryProvider.Bind(this.DataAccessModel, this.sqlDataTypeProvider, expression);
            expression = SqlQueryProvider.Optimize(this.DataAccessModel, this.SqlDatabaseContext, expression);
            var projectionExpression = expression as SqlProjectionExpression;

            expression = projectionExpression.Select.From;

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression);

            IDbCommand command = null;

            try
            {
                command             = this.CreateCommand();
                command.CommandText = result.CommandText;

                var cachedValue = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result
                };

                FillParameters(command, cachedValue, null, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
예제 #5
0
        protected virtual IDbCommand BuildUpdateCommand(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject)
        {
            bool       valuesPredicated;
            bool       primaryKeysPredicated;
            IDbCommand command = null;
            SqlCachedUpdateInsertFormatValue cachedValue;
            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;
            var updatedProperties      = dataAccessObject.ToObjectInternal().GetChangedPropertiesFlattened(out valuesPredicated);

            if (updatedProperties.Count == 0)
            {
                return(null);
            }

            var success     = false;
            var primaryKeys = dataAccessObject.ToObjectInternal().GetPrimaryKeysForUpdateFlattened(out primaryKeysPredicated);

            if (valuesPredicated || primaryKeysPredicated)
            {
                return(BuildUpdateCommandForDeflatedPredicated(typeDescriptor, dataAccessObject, valuesPredicated, primaryKeysPredicated, updatedProperties, primaryKeys));
            }

            var commandKey = new SqlCachedUpdateInsertFormatKey(dataAccessObject.GetType(), updatedProperties, requiresIdentityInsert);

            if (this.TryGetUpdateCommand(commandKey, out cachedValue))
            {
                try
                {
                    command             = this.CreateCommand();
                    command.CommandText = cachedValue.formatResult.CommandText;

                    this.FillParameters(command, cachedValue, updatedProperties, primaryKeys);

                    success = true;

                    return(command);
                }
                finally
                {
                    if (!success)
                    {
                        command?.Dispose();
                    }
                }
            }

            var constantPlaceholdersCount = 0;
            var valueIndexesToParameterPlaceholderIndexes      = new int[updatedProperties.Count];
            var primaryKeyIndexesToParameterPlaceholderIndexes = new int[primaryKeys.Length];

            var assignments = new List <Expression>(updatedProperties.Count);

            foreach (var updated in updatedProperties)
            {
                var value = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));

                if (value.Type != updated.PropertyType)
                {
                    value = Expression.Convert(value, updated.PropertyType);
                }

                assignments.Add(new SqlAssignExpression(new SqlColumnExpression(updated.PropertyType, null, updated.PersistedName), value));
            }

            Expression where = null;

            Debug.Assert(primaryKeys.Length > 0);

            foreach (var primaryKey in primaryKeys)
            {
                var value       = primaryKey.Value;
                var placeholder = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(value, primaryKey.PropertyType.CanBeNull() ? primaryKey.PropertyType : primaryKey.PropertyType.MakeNullable()));

                if (placeholder.Type != primaryKey.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, primaryKey.PropertyType);
                }

                var currentExpression = Expression.Equal(new SqlColumnExpression(primaryKey.PropertyType, null, primaryKey.PersistedName), placeholder);

                where = where == null ? currentExpression : Expression.And(where, currentExpression);
            }

            for (var i = 0; i < assignments.Count; i++)
            {
                valueIndexesToParameterPlaceholderIndexes[i] = i;
            }

            for (var i = 0; i < primaryKeys.Length; i++)
            {
                primaryKeyIndexesToParameterPlaceholderIndexes[i] = i + assignments.Count;
            }

            var expression = (Expression) new SqlUpdateExpression(new SqlTableExpression(typeDescriptor.PersistedName), assignments, where, requiresIdentityInsert);

            expression = SqlObjectOperandComparisonExpander.Expand(expression);

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression, SqlQueryFormatterOptions.Default);

            try
            {
                command             = this.CreateCommand();
                command.CommandText = result.CommandText;

                cachedValue = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result, valueIndexesToParameterPlaceholderIndexes = valueIndexesToParameterPlaceholderIndexes, primaryKeyIndexesToParameterPlaceholderIndexes = primaryKeyIndexesToParameterPlaceholderIndexes
                };

                if (result.Cacheable)
                {
                    this.CacheUpdateCommand(commandKey, cachedValue);
                }

                FillParameters(command, cachedValue, null, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
예제 #6
0
        protected IDbCommand BuildUpdateCommandForDeflatedPredicated(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject, bool valuesPredicated, bool primaryKeysPredicated, List <ObjectPropertyValue> updatedProperties, ObjectPropertyValue[] primaryKeys)
        {
            var constantPlaceholdersCount = 0;
            var assignments = new List <Expression>();
            var success     = false;

            var parameter1             = Expression.Parameter(typeDescriptor.Type);
            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;

            foreach (var updated in updatedProperties)
            {
                var value       = updated.Value;
                var placeholder = updated.Value as Expression;

                if (placeholder == null)
                {
                    placeholder = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));
                }

                if (placeholder.Type != updated.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, updated.PropertyType);
                }

                var m = TypeUtils.GetMethod(() => default(DataAccessObject).SetColumnValue(default(string), default(int)))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(typeDescriptor.Type, updated.PropertyType);

                assignments.Add(Expression.Call(null, m, parameter1, Expression.Constant(updated.PersistedName), placeholder));
            }

            var parameter = Expression.Parameter(typeDescriptor.Type);

            if (primaryKeys.Length <= 0)
            {
                throw new InvalidOperationException("Expected more than 1 primary key");
            }

            Expression where = null;

            foreach (var primaryKey in primaryKeys)
            {
                var value       = primaryKey.Value;
                var placeholder = primaryKey.Value as Expression;

                if (placeholder == null)
                {
                    placeholder = new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(value, primaryKey.PropertyType.CanBeNull() ? primaryKey.PropertyType : primaryKey.PropertyType.MakeNullable()));
                }

                if (placeholder.Type != primaryKey.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, primaryKey.PropertyType);
                }

                var pathComponents     = primaryKey.PropertyName.Split('.');
                var propertyExpression = pathComponents.Aggregate <string, Expression>(parameter, Expression.Property);
                var currentExpression  = Expression.Equal(propertyExpression, placeholder);

                where = where == null ? currentExpression : Expression.And(where, currentExpression);
            }

            var predicate = Expression.Lambda(where, parameter);
            var method    = TypeUtils.GetMethod(() => default(IQueryable <DataAccessObject>).UpdateHelper(default(Expression <Action <DataAccessObject> >), requiresIdentityInsert))
                            .GetGenericMethodDefinition()
                            .MakeGenericMethod(typeDescriptor.Type);

            var source     = Expression.Call(null, MethodInfoFastRef.QueryableWhereMethod.MakeGenericMethod(typeDescriptor.Type), Expression.Constant(this.DataAccessModel.GetDataAccessObjects(typeDescriptor.Type)), Expression.Quote(predicate));
            var selector   = Expression.Lambda(Expression.Block(assignments), parameter1);
            var expression = (Expression)Expression.Call(null, method, source, Expression.Quote(selector), Expression.Constant(requiresIdentityInsert));

            expression = SqlQueryProvider.Bind(this.DataAccessModel, this.sqlDataTypeProvider, expression);
            expression = SqlQueryProvider.Optimize(this.DataAccessModel, this.SqlDatabaseContext, expression);
            var projectionExpression = expression as SqlProjectionExpression;

            expression = projectionExpression.Select.From;

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression);

            IDbCommand command = null;

            try
            {
                command = this.CreateCommand();

                command.CommandText = result.CommandText;

                var cachedValue = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result
                };

                FillParameters(command, cachedValue, null, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
예제 #7
0
        private void FillParameters(IDbCommand command, SqlCachedUpdateInsertFormatValue cachedValue, IReadOnlyCollection <ObjectPropertyValue> changedProperties, IReadOnlyCollection <ObjectPropertyValue> primaryKeys)
        {
            if (changedProperties == null && primaryKeys == null)
            {
                foreach (var parameter in cachedValue.formatResult.ParameterValues)
                {
                    this.AddParameter(command, parameter.Type, parameter.Value);
                }

                return;
            }

            if (cachedValue.formatResult.ParameterValues.Count == (changedProperties?.Count ?? 0) + (primaryKeys?.Count ?? 0))
            {
                foreach (var value in changedProperties)
                {
                    this.AddParameter(command, value.PropertyType, value.Value);
                }

                if (primaryKeys != null)
                {
                    foreach (var value in primaryKeys)
                    {
                        this.AddParameter(command, value.PropertyType, value.Value);
                    }
                }

                return;
            }

            var newParameters = new List <TypedValue>(cachedValue.formatResult.ParameterValues);

            if (changedProperties != null)
            {
                var i = 0;

                foreach (var changed in changedProperties)
                {
                    var temp = cachedValue.valueIndexesToParameterPlaceholderIndexes[i];
                    int parameterIndex;

                    if (cachedValue.formatResult.PlaceholderIndexToParameterIndex.TryGetValue(temp, out parameterIndex))
                    {
                        var typedValue = newParameters[parameterIndex];

                        newParameters[parameterIndex] = typedValue.ChangeValue(changed.Value);
                    }

                    i++;
                }
            }

            if (primaryKeys != null)
            {
                var i = 0;

                foreach (var changed in primaryKeys)
                {
                    var temp = cachedValue.primaryKeyIndexesToParameterPlaceholderIndexes[i];
                    int parameterIndex;

                    if (cachedValue.formatResult.PlaceholderIndexToParameterIndex.TryGetValue(temp, out parameterIndex))
                    {
                        var typedValue = newParameters[parameterIndex];

                        newParameters[parameterIndex] = typedValue.ChangeValue(changed.Value);
                    }

                    i++;
                }
            }

            foreach (var parameter in newParameters)
            {
                this.AddParameter(command, parameter.Type, parameter.Value);
            }
        }
        protected void CacheUpdateCommand(SqlCachedUpdateInsertFormatKey sqlCachedUpdateInsertFormatKey, SqlCachedUpdateInsertFormatValue sqlCachedUpdateInsertFormatValue)
        {
            var newDictionary = new Dictionary <SqlCachedUpdateInsertFormatKey, SqlCachedUpdateInsertFormatValue>(this.SqlDatabaseContext.formattedUpdateSqlCache, CommandKeyComparer.Default)
            {
                [sqlCachedUpdateInsertFormatKey] = sqlCachedUpdateInsertFormatValue
            };

            this.SqlDatabaseContext.formattedUpdateSqlCache = newDictionary;
        }