示例#1
0
        internal static Param[] GetUpdateParameters(object dataEntity, IDictionary <PropertyInfo, ReflectedProperty> propertyMap, int statementId = -1)
        {
            var parameters = propertyMap.Values
                             .Where(p => p.IsPersistent && (p.IsSimpleType || p.IsSimpleList) && (p.CanWrite || p.IsAutoGenerated))
                             .Select(p => new Param
            {
                Name            = (p.ParameterName.NullIfEmpty() ?? p.PropertyName) + (statementId == -1 ? string.Empty : "_" + statementId),
                Value           = GetParameterValue(dataEntity, p),
                DbType          = Reflector.ClrToDbType(p.PropertyType),
                Direction       = p.Direction,
                Source          = p.MappedColumnName,
                IsAutoGenerated = p.IsAutoGenerated,
                IsPrimaryKey    = p.IsPrimaryKey
            });

            return(parameters.ToArray());
        }
示例#2
0
        internal static async Task <OperationResponse> ExecuteAsync(string operationText, IEnumerable <Param> parameters, OperationReturnType returnType, OperationType operationType, IList <Type> types = null, string connectionName = null, DbConnection connection = null, DbTransaction transaction = null, bool captureException = false, string schema = null, string connectionStringSection = "ConnectionStrings", IConfiguration config = null)
        {
            var rootType = types?[0];

            DbConnection dbConnection;
            var          closeConnection = false;

            if (transaction != null)
            {
                dbConnection = transaction.Connection;
            }
            else if (connection != null)
            {
                dbConnection = connection;
            }
            else
            {
                dbConnection    = DbFactory.CreateConnection(connectionName, rootType, config);
                closeConnection = true;
            }

            if (returnType == OperationReturnType.Guess)
            {
                if (operationText.IndexOf("insert", StringComparison.OrdinalIgnoreCase) > -1 ||
                    operationText.IndexOf("update", StringComparison.OrdinalIgnoreCase) > -1 ||
                    operationText.IndexOf("delete", StringComparison.OrdinalIgnoreCase) > -1)
                {
                    returnType = OperationReturnType.NonQuery;
                }
                else
                {
                    returnType = OperationReturnType.SingleResult;
                }
            }

            Dictionary <DbParameter, Param> outputParameters = null;

            var command = dbConnection.CreateCommand();

            command.CommandText    = operationText;
            command.CommandType    = operationType == OperationType.StoredProcedure ? CommandType.StoredProcedure : CommandType.Text;
            command.CommandTimeout = 0;
            if (parameters != null)
            {
                ISet <string> parsedParameters = null;
                if ((config?.IgnoreInvalidParameters).GetValueOrDefault())
                {
                    if (operationType == OperationType.StoredProcedure)
                    {
                        parsedParameters = DbFactory.GetProcedureParameters(dbConnection, operationText, true, config);
                    }
                    else
                    {
                        parsedParameters = DbFactory.GetQueryParameters(dbConnection, operationText, true, config);
                    }
                }

                foreach (var parameter in parameters)
                {
                    var name = parameter.Name.TrimStart('@', '?', ':');

                    if (parsedParameters != null && !parsedParameters.Contains(name))
                    {
                        continue;
                    }

                    var dbParam = command.CreateParameter();
                    dbParam.ParameterName = name;
                    dbParam.Direction     = parameter.Direction;
                    dbParam.Value         = parameter.Value ?? DBNull.Value;

                    if (parameter.Value != null)
                    {
                        if (parameter.Size > -1)
                        {
                            dbParam.Size = parameter.Size;
                        }

                        dbParam.DbType = parameter.DbType ?? Reflector.ClrToDbType(parameter.Type);
                    }
                    else if (parameter.DbType != null)
                    {
                        dbParam.DbType = parameter.DbType.Value;
                    }

                    if (dbParam.Direction == ParameterDirection.Output)
                    {
                        if (outputParameters == null)
                        {
                            outputParameters = new Dictionary <DbParameter, Param>();
                        }
                        outputParameters.Add(dbParam, parameter);
                    }

                    command.Parameters.Add(dbParam);
                }
            }

            if (dbConnection.State != ConnectionState.Open)
            {
                await dbConnection.OpenAsync().ConfigureAwait(false);
            }

            var response = new OperationResponse {
                ReturnType = returnType
            };

            try
            {
                switch (returnType)
                {
                case OperationReturnType.NonQuery:
                    response.RecordsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false);

                    break;

                case OperationReturnType.MultiResult:
                case OperationReturnType.SingleResult:
                case OperationReturnType.SingleRow:
                    var behavior = CommandBehavior.Default;
                    switch (returnType)
                    {
                    case OperationReturnType.SingleResult:
                        behavior = CommandBehavior.SingleResult;
                        break;

                    case OperationReturnType.SingleRow:
                        behavior = CommandBehavior.SingleRow;
                        break;

                    default:
                        closeConnection = false;
                        break;
                    }

                    if (closeConnection)
                    {
                        behavior |= CommandBehavior.CloseConnection;
                    }

                    closeConnection = false;
                    response.Value  = await command.ExecuteReaderAsync(behavior).ConfigureAwait(false);

                    break;

                case OperationReturnType.Scalar:
                    response.Value = await command.ExecuteScalarAsync().ConfigureAwait(false);

                    break;
                }

                // Handle output parameters
                if (outputParameters != null)
                {
                    foreach (var entry in outputParameters)
                    {
                        entry.Value.Value = Convert.IsDBNull(entry.Key.Value) ? null : entry.Key.Value;
                    }
                }
            }
            catch (Exception ex)
            {
                if (captureException)
                {
                    response.Exception = ex;
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                command.Dispose();
                if (dbConnection != null && (closeConnection || response.HasErrors))
                {
                    dbConnection.Close();
                }
            }

            return(response);
        }
示例#3
0
        private static Tuple <string, Param[], List <object> > GetCommitStatement(ChangeNode rootNode, DbConnection connection)
        {
            var dialect      = DialectFactory.GetProvider(connection);
            var dataEntities = new List <object>();
            var sql          = new StringBuilder();
            var statementId  = 0;

            // Inserts
            var newNodes     = GetChanges(rootNode, ObjectState.New);
            var tableCreated = false;

            var tempTableName = dialect.GetTemporaryTableName("ID");
            var allParameters = new List <Param>();

            foreach (var newNode in newNodes.Where(n => n.IsObject))
            {
                var item = newNode.Value;
                if (item != null)
                {
                    dataEntities.Add(item);
                }
                else
                {
                    continue;
                }

                var objectType      = newNode.Value.GetType();
                var propertyMap     = Reflector.GetPropertyMap(objectType);
                var autoGenProperty = propertyMap.Where(p => p.Key.CanWrite && p.Value != null && p.Value.IsAutoGenerated).Select(p => p.Key).FirstOrDefault();
                var autoGenType     = DbType.String;

                if (!tableCreated)
                {
                    if (autoGenProperty != null)
                    {
                        autoGenType = Reflector.ClrToDbType(autoGenProperty.PropertyType);
                    }
                    sql.AppendFormat(dialect.CreateTemporaryTable("ID", new Dictionary <string, DbType> {
                        { "StatementId", DbType.Int32 }, { "GeneratedId", autoGenType }, { "ParameterName", DbType.AnsiString }, { "PropertyName", DbType.AnsiString }
                    })).AppendLine();
                    tableCreated = true;
                }

                var parameters = ObjectExtensions.GetInsertParameters(newNode.Value, propertyMap, statementId);
                allParameters.AddRange(parameters);

                if (parameters.Length > 0)
                {
                    string commandName      = SqlBuilder.GetInsertStatement(objectType, parameters, dialect);
                    var    autoGenParameter = parameters.FirstOrDefault(p => p.IsAutoGenerated);

                    if (autoGenParameter != null)
                    {
                        sql.AppendFormat(dialect.DeclareVariable(autoGenParameter.Name, autoGenType)).AppendLine();
                        sql.AppendFormat(dialect.AssignVariable(autoGenParameter.Name, autoGenParameter.Type.GetDefault())).AppendLine();
                    }
                    sql.AppendLine(commandName);

                    if (autoGenParameter != null)
                    {
                        sql.AppendFormat(dialect.ComputeAutoIncrement(autoGenParameter.Name, () => SqlBuilder.GetTableNameForSql(objectType, dialect))).AppendLine();
                        sql.AppendFormat("INSERT INTO " + tempTableName + " ({4}StatementId{5}, {4}GeneratedId{5}, {4}ParameterName{5}, {4}PropertyName{5}) VALUES ({0}, {1}, '{2}', '{3}')", statementId, dialect.EvaluateVariable(dialect.ParameterPrefix + autoGenParameter.Name), autoGenParameter.Name, autoGenProperty.Name, dialect.IdentifierEscapeStartCharacter, dialect.IdentifierEscapeEndCharacter).AppendLine();
                    }

                    statementId++;
                }
            }

            if (newNodes.Count > 0)
            {
                sql.AppendLine("SELECT * FROM " + tempTableName);
            }

            if (tableCreated && !dialect.SupportsTemporaryTables)
            {
                sql.AppendLine("DROP TABLE " + tempTableName);
            }

            // Updates
            var dirtyNodes       = GetChanges(rootNode, ObjectState.Dirty);
            var dirtyNodeParents = dirtyNodes.Where(n => n.IsSimpleLeaf).Select(n => n.Parent).Distinct();

            foreach (var dirtyNode in dirtyNodeParents)
            {
                var objectType  = dirtyNode.Value.GetType();
                var propertyMap = Reflector.GetPropertyMap(objectType).ToDictionary(p => p.Key.Name, p => p);

                var parameters = new List <Param>();
                foreach (var change in dirtyNode.Nodes.Where(n => n.IsSimpleLeaf))
                {
                    KeyValuePair <PropertyInfo, ReflectedProperty> map;
                    if (propertyMap.TryGetValue(change.PropertyName, out map))
                    {
                        var property      = map.Key;
                        var parameterName = change.PropertyName;
                        if (map.Value != null && !string.IsNullOrEmpty(map.Value.ParameterName))
                        {
                            parameterName = map.Value.ParameterName;
                        }

                        parameters.Add(new Param {
                            Name = parameterName + "_" + statementId, Value = change.Value, Source = MapColumnAttribute.GetMappedColumnName(property)
                        });
                    }
                }

                var primaryKey = new List <Param>();
                foreach (var primaryKeyMap in propertyMap.Values.Where(p => p.Value.IsPrimaryKey))
                {
                    var value = dirtyNode.Value.Property(primaryKeyMap.Key.Name);

                    var parameterName = primaryKeyMap.Key.Name;
                    if (primaryKeyMap.Value != null && !string.IsNullOrEmpty(primaryKeyMap.Value.ParameterName))
                    {
                        parameterName = primaryKeyMap.Value.ParameterName;
                    }
                    primaryKey.Add(new Param {
                        Name = parameterName + "_" + statementId, Value = value, Source = MapColumnAttribute.GetMappedColumnName(primaryKeyMap.Key)
                    });
                }

                var commandName = SqlBuilder.GetUpdateStatement(objectType, parameters, primaryKey, dialect);
                allParameters.AddRange(parameters);
                allParameters.AddRange(primaryKey);
                sql.Append(commandName).AppendLine();

                statementId++;
            }

            // Deletes
            var deletedNodes = GetChanges(rootNode, ObjectState.Deleted);

            foreach (var deletedNode in deletedNodes)
            {
                var objectType  = deletedNode.Value.GetType();
                var propertyMap = Reflector.GetPropertyMap(objectType);

                var parameters  = ObjectExtensions.GetDeleteParameters(deletedNode.Value, propertyMap, statementId);
                var commandName = SqlBuilder.GetDeleteStatement(objectType, parameters, dialect);
                allParameters.AddRange(parameters);
                sql.Append(commandName).AppendLine();

                statementId++;
            }

            return(Tuple.Create(sql.ToString(), allParameters.ToArray(), dataEntities));
        }