/// <summary> /// Initializes a new instance of the <see cref="UnitOfWork" /> class. /// </summary> /// <param name="context">The database context.</param> /// <param name="databaseProvider"> /// The database provider that inherited from /// <see cref="System.Data.Entity.Core.Common.DbProviderServices" /> abstract class. /// </param> /// <param name="dbCommandInterceptor">The database command interceptor for logging.</param> /// <param name="lazyLoad">if set to <c>true</c> EF will not load related entities, you should manual load that by eager loading. /// by default EF set this flag is <c>false</c>.</param> /// <exception cref="System.ArgumentNullException">When context parameter is null.</exception> /// <exception cref="System.ArgumentException">When database does not exist. This exception will occur when set checkDbExists to true.</exception> public UnitOfWork(TDbContext context, System.Data.Entity.Core.Common.DbProviderServices databaseProvider, IDbCommandInterceptor dbCommandInterceptor = null, bool lazyLoad = true) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // Disables auto-generate database. Database.SetInitializer <TDbContext>(null); _context = context; // Sets to false for high performance but has to use with ChangeTracker.DetectChanges method to detect later when you want. _context.Configuration.AutoDetectChangesEnabled = false; // Sets to false for high performance but has to use with eager loading for all navigation properties // you want to use (Include on ObjectQuery), by default EF will set to false and no need to use eager loading // EF will automatic lading all related entities at first times. // <a href="https://msdn.microsoft.com/en-us/data/hh949853.aspx" target="_blank"> For more information.</a> _context.Configuration.LazyLoadingEnabled = lazyLoad; // Adds interceptor for logging all sql scripts. if (dbCommandInterceptor != null) { DbInterception.Add(dbCommandInterceptor); } // Initializes container. _repositoriesContainer = new Dictionary <string, dynamic>(); }
public void Dispose() { if (_commandInterceptor != null) { _commandInterceptor.IsEnabled = false; _commandInterceptor = null; } }
/// <summary> /// Creates a new instance with all options the same as for this instance, but with the given option changed. /// It is unusual to call this method directly. Instead use <see cref="DbContextOptionsBuilder" />. /// </summary> /// <param name="commandInterceptor"> The option to change. </param> /// <returns> A new instance with the option changed. </returns> public virtual RelationalOptionsExtension WithCommandInterceptor( [CanBeNull] IDbCommandInterceptor commandInterceptor) { var clone = Clone(); clone._commandInterceptor = commandInterceptor; return(clone); }
public CommandTracer(IDbCommandInterceptor commandInterceptor = null) { _commandInterceptor = commandInterceptor ?? DbConfiguration.GetService<IDbCommandInterceptor>(); if (_commandInterceptor != null) { _commandInterceptor.IsEnabled = true; } }
public CommandTracer(IDbCommandInterceptor commandInterceptor = null) { _commandInterceptor = commandInterceptor ?? DbConfiguration.GetService <IDbCommandInterceptor>(); if (_commandInterceptor != null) { _commandInterceptor.IsEnabled = true; } }
/// <summary> /// We resolve this lazily because loggers are created very early in the initialization /// process where <see cref="IDbContextOptions"/> is not yet available from D.I. /// This means those loggers can't do interception, but that's okay because nothing /// else is ready for them to do interception anyway. /// </summary> private bool TryFindAppInterceptor(out IDbCommandInterceptor interceptor) { interceptor = Dependencies .ServiceProvider .GetService <IDbContextOptions>() .Extensions .OfType <RelationalOptionsExtension>() .FirstOrDefault() ?.CommandInterceptor; return(interceptor != null); }
public static void Add(IDbCommandInterceptor interceptor) { PublicHelper.CheckNull(interceptor); lock (_lockObject) { List <IDbCommandInterceptor> newList = _interceptors.ToList(); newList.Add(interceptor); newList.TrimExcess(); _interceptors = newList; } }
public static void Remove(IDbCommandInterceptor interceptor) { Checks.NotNull(interceptor, "interceptor"); lock (_lockObject) { List <IDbCommandInterceptor> newList = _interceptors.ToList(); newList.Remove(interceptor); newList.TrimExcess(); _interceptors = newList; } }
/// <summary> /// Called by a derived class constructor when implementing the <see cref="Clone" /> method. /// </summary> /// <param name="copyFrom"> The instance that is being cloned. </param> protected RelationalOptionsExtension([NotNull] RelationalOptionsExtension copyFrom) { Check.NotNull(copyFrom, nameof(copyFrom)); _connectionString = copyFrom._connectionString; _connection = copyFrom._connection; _commandTimeout = copyFrom._commandTimeout; _maxBatchSize = copyFrom._maxBatchSize; _minBatchSize = copyFrom._minBatchSize; _useRelationalNulls = copyFrom._useRelationalNulls; _migrationsAssembly = copyFrom._migrationsAssembly; _migrationsHistoryTableName = copyFrom._migrationsHistoryTableName; _migrationsHistoryTableSchema = copyFrom._migrationsHistoryTableSchema; _executionStrategyFactory = copyFrom._executionStrategyFactory; _commandInterceptor = copyFrom._commandInterceptor; }
public EntityStoreSchemaGeneratorDatabaseSchemaLoader( EntityConnection entityConnection, Version storeSchemaModelVersion) { Debug.Assert(entityConnection != null, "entityConnection != null"); Debug.Assert(entityConnection.State == ConnectionState.Closed, "expected closed connection"); Debug.Assert(EntityFrameworkVersion.IsValidVersion(storeSchemaModelVersion), "invalid version"); _connection = entityConnection; _storeSchemaModelVersion = storeSchemaModelVersion; if (_connection != null && _connection.StoreConnection != null && string.Equals( _connection.StoreConnection.GetProviderInvariantName(), SqlServerInvariantName, StringComparison.Ordinal) && !SwitchOffMetadataMergeJoins()) { _addOptionMergeJoinInterceptor = new AddOptionMergeJoinInterceptor(); } }
public EntityStoreSchemaGeneratorDatabaseSchemaLoader( EntityConnection entityConnection, Version storeSchemaModelVersion) { Debug.Assert(entityConnection != null, "entityConnection != null"); Debug.Assert(entityConnection.State == ConnectionState.Closed, "expected closed connection"); Debug.Assert(EntityFrameworkVersion.IsValidVersion(storeSchemaModelVersion), "invalid version"); _connection = entityConnection; _storeSchemaModelVersion = storeSchemaModelVersion; var isSqlServer = false; try { if (_connection != null && _connection.StoreConnection != null && string.Equals( _connection.StoreConnection.GetProviderInvariantName(), SqlServerInvariantName, StringComparison.Ordinal)) { isSqlServer = true; } } catch (Exception) { // Several exceptions can be thrown from GetProviderInvariantName(). // Assume that the provider is not SqlServer unless we can confirm it is. } if (isSqlServer && !SwitchOffMetadataMergeJoins()) { _addOptionMergeJoinInterceptor = new AddOptionMergeJoinInterceptor(); } }
/// <summary> /// Initializes a new instance of the <see cref="TraceableSqlCommand"/> class. /// </summary> /// <param name="collectSqlQueries"> /// Include the <see cref="TraceableSqlCommand.CommandText" /> in the sanitized_query section of /// the SQL subsegment. Parameterized values will appear in their tokenized form and will not be expanded. /// You should not enable this flag if you are including sensitive information as clear text. /// This flag will override any behavior configured by <see cref="XRayOptions.CollectSqlQueries" />. /// If a value is not provided, then the globally configured value will be used, which is false by default. /// See the official documentation on <a href="https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netframework-4.7.2">SqlCommand.Parameters</a> /// </param> public TraceableSqlCommand(bool?collectSqlQueries = null) { InnerSqlCommand = new SqlCommand(); _interceptor = new DbCommandInterceptor(AWSXRayRecorder.Instance, collectSqlQueries); }
/// <summary> /// Initializes the interceptor /// </summary> public ProfilingInterceptor() { this._internalInstance = DependencyFactory.GetService<IDbCommandInterceptor>(); }
/// <summary> /// <para> /// Configures the context to use the given <see cref="IDbCommandInterceptor" />. /// </para> /// <para> /// Note that only a single <see cref="IDbCommandInterceptor" /> can be registered. /// Use <see cref="CompositeDbCommandInterceptor"/> to combine multiple interceptors into one. /// </para> /// </summary> /// <param name="interceptor"> The interceptor to use. </param> public virtual TBuilder CommandInterceptor( [NotNull] IDbCommandInterceptor interceptor) => WithOption(e => (TExtension)e.WithCommandInterceptor(Check.NotNull(interceptor, nameof(interceptor))));
/// <summary> /// See comments in <see cref="UpdateCommand" />. /// </summary> internal override long Execute( Dictionary <int, object> identifierValues, List <KeyValuePair <PropagatorResult, object> > generatedValues, IDbCommandInterceptor commandInterceptor) { // Compile command using (var command = CreateCommand(identifierValues)) { var connection = Translator.Connection; // configure command to use the connection and transaction for this session command.Transaction = ((null == connection.CurrentTransaction) ? null : connection.CurrentTransaction.StoreTransaction); command.Connection = connection.StoreConnection; if (Translator.CommandTimeout.HasValue) { command.CommandTimeout = Translator.CommandTimeout.Value; } // Execute the query int rowsAffected; if (_modificationCommandTree.HasReader) { // retrieve server gen results rowsAffected = 0; using (var reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) { if (reader.Read()) { rowsAffected++; var members = TypeHelpers.GetAllStructuralMembers(CurrentValues.StructuralType); for (var ordinal = 0; ordinal < reader.FieldCount; ordinal++) { // column name of result corresponds to column name of table var columnName = reader.GetName(ordinal); var member = members[columnName]; object value; if (Helper.IsSpatialType(member.TypeUsage) && !reader.IsDBNull(ordinal)) { value = SpatialHelpers.GetSpatialValue(Translator.MetadataWorkspace, reader, member.TypeUsage, ordinal); } else { value = reader.GetValue(ordinal); } // retrieve result which includes the context for back-propagation var columnOrdinal = members.IndexOf(member); var result = CurrentValues.GetMemberValue(columnOrdinal); // register for back-propagation generatedValues.Add(new KeyValuePair <PropagatorResult, object>(result, value)); // register identifier if it exists var identifier = result.Identifier; if (PropagatorResult.NullIdentifier != identifier) { identifierValues.Add(identifier, value); } } } // Consume the current reader (and subsequent result sets) so that any errors // executing the command can be intercepted CommandHelper.ConsumeReader(reader); } } else { // We currently only intercept commands on this code path. var executeCommand = true; if (commandInterceptor != null) { executeCommand = commandInterceptor.Intercept(command); } rowsAffected = executeCommand ? command.ExecuteNonQuery() : 1; } return(rowsAffected); } }
public WithInterception(IDbCommandInterceptor interceptor) { this.interceptor = interceptor; DbInterception.Add(this.interceptor); }
protected abstract void RemoveInterceptor(IDbCommandInterceptor interceptor);
public void RemoveInterceptor(IDbCommandInterceptor interceptor) { PublicHelper.CheckNull(interceptor, "interceptor"); this._dbContext.AdoSession.SessionInterceptors.Remove(interceptor); }
/// <summary> /// 移除拦截器 /// </summary> public static void Remove(IDbCommandInterceptor interceptor) { _interceptors.Remove(interceptor); }
public void RemoveInterceptor(IDbCommandInterceptor interceptor) { Utils.CheckNull(interceptor, "interceptor"); this._dbContext.AdoSession.DbCommandInterceptors.Remove(interceptor); }
public void AddInterceptor(IDbCommandInterceptor interceptor) { Utils.CheckNull(interceptor, "interceptor"); this._dbContext.InnerDbSession.DbCommandInterceptors.Add(interceptor); }
/// <summary> /// See comments in <see cref="UpdateCommand" />. /// </summary> internal override long Execute( Dictionary <int, object> identifierValues, List <KeyValuePair <PropagatorResult, object> > generatedValues, IDbCommandInterceptor commandInterceptor) { var connection = Translator.Connection; // configure command to use the connection and transaction for this session _dbCommand.Transaction = ((null == connection.CurrentTransaction) ? null : connection.CurrentTransaction.StoreTransaction); _dbCommand.Connection = connection.StoreConnection; if (Translator.CommandTimeout.HasValue) { _dbCommand.CommandTimeout = Translator.CommandTimeout.Value; } SetInputIdentifiers(identifierValues); // Execute the query long rowsAffected; if (null != ResultColumns) { // If there are result columns, read the server gen results rowsAffected = 0; var members = TypeHelpers.GetAllStructuralMembers(CurrentValues.StructuralType); using (var reader = _dbCommand.ExecuteReader(CommandBehavior.SequentialAccess)) { // Retrieve only the first row from the first result set if (reader.Read()) { rowsAffected++; foreach (var resultColumn in ResultColumns .Select(r => new KeyValuePair <int, PropagatorResult>(GetColumnOrdinal(Translator, reader, r.Key), r.Value)) .OrderBy(r => r.Key)) // order by column ordinal to avoid breaking SequentialAccess readers { var columnOrdinal = resultColumn.Key; var columnType = members[resultColumn.Value.RecordOrdinal].TypeUsage; object value; if (Helper.IsSpatialType(columnType) && !reader.IsDBNull(columnOrdinal)) { value = SpatialHelpers.GetSpatialValue(Translator.MetadataWorkspace, reader, columnType, columnOrdinal); } else { value = reader.GetValue(columnOrdinal); } // register for back-propagation var result = resultColumn.Value; generatedValues.Add(new KeyValuePair <PropagatorResult, object>(result, value)); // register identifier if it exists var identifier = result.Identifier; if (PropagatorResult.NullIdentifier != identifier) { identifierValues.Add(identifier, value); } } } // Consume the current reader (and subsequent result sets) so that any errors // executing the function can be intercepted CommandHelper.ConsumeReader(reader); } } else { rowsAffected = _dbCommand.ExecuteNonQuery(); } return(GetRowsAffected(rowsAffected, Translator)); }
/// <summary> /// Initializes a new instance of the <see cref="DSUnitOfWork" /> class. /// </summary> /// <param name="dbContext">The database context what inherits from DbContext of EF.</param> /// <param name="dbCommandInterceptor">The database command interceptor for logging.</param> public DSUnitOfWork(DbContext dbContext, IDbCommandInterceptor dbCommandInterceptor = null) : base(dbContext, SqlProviderServices.Instance, dbCommandInterceptor) { }
/// <summary> /// Executes the current update command. /// All server-generated values are added to the generatedValues list. If those values are identifiers, they are /// also added to the identifierValues dictionary, which associates proxy identifiers for keys in the session /// with their actual values, permitting fix-up of identifiers across relationships. /// </summary> /// <param name="identifierValues"> Aggregator for identifier values (read for InputIdentifiers; write for OutputIdentifiers </param> /// <param name="generatedValues"> Aggregator for server generated values. </param> /// <returns> Number of rows affected by the command. </returns> internal abstract long Execute( Dictionary <int, object> identifierValues, List <KeyValuePair <PropagatorResult, object> > generatedValues, IDbCommandInterceptor commandInterceptor);
/// <summary> /// 注册拦截器 /// </summary> public static void Add(IDbCommandInterceptor interceptor) { _interceptors.Add(interceptor); }
/// <summary> /// Initializes a new instance of the <see cref="TraceableSqlCommand"/> class. /// </summary> /// <param name="cmdText">The text of the query.</param> /// <param name="connection">The connection to an instance of SQL Server.</param> /// <param name="collectSqlQueries"> /// Include the <see cref="TraceableSqlCommand.CommandText" /> in the sanitized_query section of /// the SQL subsegment. Parameterized values will appear in their tokenized form and will not be expanded. /// You should not enable this flag if you are including sensitive information as clear text. /// This flag will override any behavior configured by <see cref="XRayOptions.CollectSqlQueries" />. /// If a value is not provided, then the globally configured value will be used, which is false by default. /// See the official documentation on <a href="https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netframework-4.7.2">SqlCommand.Parameters</a> /// </param> public TraceableSqlCommand(string cmdText, SqlConnection connection, bool?collectSqlQueries = null) { InnerSqlCommand = new SqlCommand(cmdText, connection); _interceptor = new DbCommandInterceptor(AWSXRayRecorder.Instance, collectSqlQueries); }
public static TResult WithCommandInterceptor <TContext, TResult>(this TContext context, Func <TContext, TResult> function, IDbCommandInterceptor interceptor) where TContext : DbContext { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (function == null) { throw new ArgumentNullException(nameof(function)); } if (interceptor == null) { throw new ArgumentNullException(nameof(interceptor)); } DbInterception.Add(interceptor); var result = function(context); DbInterception.Remove(interceptor); return(result); }
protected abstract void AddInterceptor(IDbCommandInterceptor interceptor);