예제 #1
0
파일: CacheKey.cs 프로젝트: rhutchison/Nemo
        protected CacheKey(IDictionary<string, object> key, Type type, string operation, OperationReturnType returnType, bool sorted, HashAlgorithmName hashAlgorithm = HashAlgorithmName.Default)
        {
            var reflectedType = Reflector.GetReflectedType(type);
            var typeName = reflectedType.IsBusinessObject && reflectedType.InterfaceTypeName != null ? reflectedType.InterfaceTypeName : reflectedType.FullTypeName;

            _hashAlgorithm = hashAlgorithm == HashAlgorithmName.Default ? ObjectFactory.Configuration.DefaultHashAlgorithm : hashAlgorithm;
            if (_hashAlgorithm == HashAlgorithmName.Native || _hashAlgorithm == HashAlgorithmName.None)
            {
                var keyValue = (sorted ? key.Select(k => string.Format("{0}={1}", k.Key, Uri.EscapeDataString(Convert.ToString(k.Value)))) : key.OrderBy(k => k.Key).Select(k => string.Format("{0}={1}", k.Key, Uri.EscapeDataString(Convert.ToString(k.Value))))).ToDelimitedString("&");
                if (!string.IsNullOrEmpty(operation))
                {
                    _value = string.Concat(typeName, "->", operation, "[", returnType, "]", "::", keyValue);
                }
                else
                {
                    _value = string.Concat(typeName, "::", keyValue);
                }
                _data = _value.ToByteArray();
            }
            else
            {
                Func<KeyValuePair<string, object>, IEnumerable<byte>> func = k => BitConverter.GetBytes(k.Key.GetHashCode()).Append((byte)'=').Concat(BitConverter.GetBytes(k.Value.GetHashCode())).Append((byte)'&');
                var keyValue = (sorted ? key.Select(func) : key.OrderBy(k => k.Key).Select(func)).Flatten().ToArray();
                if (!string.IsNullOrEmpty(operation))
                {
                    _data = new byte[4 + 4 + 1 + keyValue.Length];
                    Buffer.BlockCopy(BitConverter.GetBytes(typeName.GetHashCode()), 0, _data, 0, 4);
                    Buffer.BlockCopy(BitConverter.GetBytes(operation.GetHashCode()), 0, _data, 4, 4);
                    Buffer.BlockCopy(new[] { (byte)returnType }, 0, _data, 8, 1);
                    Buffer.BlockCopy(keyValue, 0, _data, 9, keyValue.Length);
                }
                else
                {
                    _data = new byte[4 + keyValue.Length];
                    Buffer.BlockCopy(BitConverter.GetBytes(typeName.GetHashCode()), 0, _data, 0 , 4);
                    Buffer.BlockCopy(keyValue, 0, _data, 4 , keyValue.Length);
                }
            }
        }
예제 #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 async Task <IEnumerable <T> > RetrieveItemsAsync <T>(string operation, IList <Param> parameters, OperationType operationType, OperationReturnType returnType, string connectionName, DbConnection connection, IList <Type> types, Func <object[], T> map, bool cached, MaterializationMode mode, string schema, IConfiguration config, IdentityMap <T> identityMap)
            where T : class
        {
            if (operationType == OperationType.Guess)
            {
                operationType = operation.Any(char.IsWhiteSpace) ? OperationType.Sql : OperationType.StoredProcedure;
            }

            var operationText = GetOperationText(typeof(T), operation, operationType, schema, config);

            var response = connection != null
                ? await ExecuteAsync(operationText, parameters, returnType, connection : connection, operationType : operationType, types : types, schema : schema)
                : await ExecuteAsync(operationText, parameters, returnType, connectionName : connectionName, operationType : operationType, types : types, schema : schema);

            var result = Translate(response, map, types, cached, mode, identityMap);

            return(result);
        }
예제 #4
0
        private static async Task <IEnumerable <TResult> > RetrieveImplemenationAsync <TResult>(string operation, OperationType operationType, IList <Param> parameters, OperationReturnType returnType, string connectionName, DbConnection connection, Func <object[], TResult> map = null, IList <Type> types = null, MaterializationMode mode = MaterializationMode.Default, string schema = null, bool?cached = null, IConfiguration config = null)
            where TResult : class
        {
            Log.CaptureBegin(() => $"RetrieveImplemenation: {typeof(TResult).FullName}::{operation}");
            IEnumerable <TResult> result;

            string queryKey = null;
            IdentityMap <TResult> identityMap = null;

            if (!cached.HasValue)
            {
                if (config == null)
                {
                    config = ConfigurationFactory.Get <TResult>();
                }

                cached = config.DefaultCacheRepresentation != CacheRepresentation.None;
            }

            if (cached.Value)
            {
                if (config == null)
                {
                    config = ConfigurationFactory.Get <TResult>();
                }

                queryKey = GetQueryKey <TResult>(operation, parameters ?? new Param[] { }, returnType);

                Log.CaptureBegin(() => $"Retrieving from L1 cache: {queryKey}");

                if (returnType == OperationReturnType.MultiResult)
                {
                    result = config.ExecutionContext.Get(queryKey) as IEnumerable <TResult>;
                }
                else
                {
                    identityMap = Identity.Get <TResult>();
                    result      = identityMap.GetIndex(queryKey);
                }

                Log.CaptureEnd();

                if (result != null)
                {
                    Log.Capture(() => $"Found in L1 cache: {queryKey}");

                    if (returnType == OperationReturnType.MultiResult)
                    {
                        ((IMultiResult)result).Reset();
                    }

                    Log.CaptureEnd();
                    return(result);
                }
                Log.Capture(() => $"Not found in L1 cache: {queryKey}");
            }

            result = await RetrieveItemsAsync(operation, parameters, operationType, returnType, connectionName, connection, types, map, cached.Value, mode, schema, config, identityMap);

            if (queryKey != null)
            {
                Log.CaptureBegin(() => $"Saving to L1 cache: {queryKey}");

                if (!(result is IList <TResult>) && !(result is IMultiResult))
                {
                    if (config.DefaultCacheRepresentation == CacheRepresentation.List)
                    {
                        result = result.ToList();
                    }
                    else
                    {
                        result = result.AsStream();
                    }
                }

                if (identityMap != null)
                {
                    result = identityMap.AddIndex(queryKey, result);
                }
                else if (result is IMultiResult)
                {
                    config.ExecutionContext.Set(queryKey, result);
                }

                Log.CaptureEnd();
            }

            Log.CaptureEnd();
            return(result);
        }
예제 #5
0
파일: CacheKey.cs 프로젝트: rhutchison/Nemo
 internal CacheKey(IDictionary<string, object> key, Type type, string operation, OperationReturnType returnType, HashAlgorithmName hashAlgorithm = HashAlgorithmName.Default)
     : this(key, type, operation, returnType, key is SortedDictionary<string, object>, hashAlgorithm)
 {
 }
예제 #6
0
파일: CacheKey.cs 프로젝트: rhutchison/Nemo
 internal CacheKey(IEnumerable<Param> parameters, Type type, string operation, OperationReturnType returnType, HashAlgorithmName hashAlgorithm = HashAlgorithmName.Default)
     : this(new SortedDictionary<string, object>(parameters.ToDictionary(p => p.Name, p => p.Value)), type, operation, returnType, hashAlgorithm)
 {
 }
예제 #7
0
파일: CacheKey.cs 프로젝트: rhutchison/Nemo
 public CacheKey(IBusinessObject businessObject, string operation, OperationReturnType returnType, HashAlgorithmName hashAlgorithm = HashAlgorithmName.Default)
     : this(businessObject.GetPrimaryKey(true), businessObject.GetType(), operation, returnType, true, hashAlgorithm)
 {
 }