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); } } }
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); }
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); }
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); }
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) { }
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) { }
public CacheKey(IBusinessObject businessObject, string operation, OperationReturnType returnType, HashAlgorithmName hashAlgorithm = HashAlgorithmName.Default) : this(businessObject.GetPrimaryKey(true), businessObject.GetType(), operation, returnType, true, hashAlgorithm) { }