diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryTransaction.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryTransaction.cs index 85384be0d02..335619c0763 100644 --- a/src/EFCore.InMemory/Storage/Internal/InMemoryTransaction.cs +++ b/src/EFCore.InMemory/Storage/Internal/InMemoryTransaction.cs @@ -1,10 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; + namespace Microsoft.EntityFrameworkCore.Storage.Internal { public class InMemoryTransaction : IDbContextTransaction { + public virtual Guid TransactionId { get; } = Guid.NewGuid(); + public virtual void Commit() { } diff --git a/src/EFCore.Relational.Design/Infrastructure/RelationalDesignEventId.cs b/src/EFCore.Relational.Design/Infrastructure/RelationalDesignEventId.cs index b1ec347bf36..015ebb35fc3 100644 --- a/src/EFCore.Relational.Design/Infrastructure/RelationalDesignEventId.cs +++ b/src/EFCore.Relational.Design/Infrastructure/RelationalDesignEventId.cs @@ -164,7 +164,7 @@ private enum Id public static readonly EventId ForeignKeyColumnMissingWarning = MakeScaffoldingId(Id.ForeignKeyColumnMissingWarning); /// - /// A foreign key column was not found. + /// A column referenced by a foreign key constraint was not found. /// This event is in the category. /// public static readonly EventId ForeignKeyPrincipalColumnMissingWarning = MakeScaffoldingId(Id.ForeignKeyPrincipalColumnMissingWarning); @@ -188,7 +188,7 @@ private enum Id public static readonly EventId IndexNotNamedWarning = MakeScaffoldingId(Id.IndexNotNamedWarning); /// - /// The table references by an index was not found. + /// The table referened by an index was not found. /// This event is in the category. /// public static readonly EventId IndexTableMissingWarning = MakeScaffoldingId(Id.IndexTableMissingWarning); diff --git a/src/EFCore.Relational.Design/Metadata/SequenceModel.cs b/src/EFCore.Relational.Design/Metadata/SequenceModel.cs index a14384a3448..407323cef72 100644 --- a/src/EFCore.Relational.Design/Metadata/SequenceModel.cs +++ b/src/EFCore.Relational.Design/Metadata/SequenceModel.cs @@ -20,6 +20,6 @@ public class SequenceModel : Annotatable public virtual bool? IsCyclic { get; [param: CanBeNull] set; } public virtual string DisplayName - => (!string.IsNullOrEmpty(SchemaName) ? SchemaName + "." : "") + Name; + => !string.IsNullOrEmpty(SchemaName) ? (SchemaName + "." + Name) : Name; } } diff --git a/src/EFCore.Relational.Design/Metadata/TableModel.cs b/src/EFCore.Relational.Design/Metadata/TableModel.cs index 73df30030fa..bec726a0e57 100644 --- a/src/EFCore.Relational.Design/Metadata/TableModel.cs +++ b/src/EFCore.Relational.Design/Metadata/TableModel.cs @@ -21,6 +21,6 @@ public class TableModel : Annotatable public virtual ICollection ForeignKeys { get; } = new List(); public virtual string DisplayName - => (!string.IsNullOrEmpty(SchemaName) ? SchemaName + "." : "") + Name; + => !string.IsNullOrEmpty(SchemaName) ? (SchemaName + "." + Name) : Name; } } diff --git a/src/EFCore.Relational/Diagnostics/CommandData.cs b/src/EFCore.Relational/Diagnostics/CommandData.cs new file mode 100644 index 00000000000..598aab06d47 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/CommandData.cs @@ -0,0 +1,85 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for + /// command events. + /// + public class CommandData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// The method. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// Indicates whether or not the command was executed asyncronously. + /// + /// + /// A timestamp from that can be used for timing. + /// + public CommandData( + [NotNull] DbCommand command, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + bool async, + long timestamp) + { + Command = command; + CommandId = commandId; + ConnectionId = connectionId; + ExecuteMethod = executeMethod; + Async = async; + Timestamp = timestamp; + } + + /// + /// The . + /// + public virtual DbCommand Command { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid CommandId { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid ConnectionId { get; } + + /// + /// The method. + /// + public virtual DbCommandMethod ExecuteMethod { get; } + + /// + /// Indicates whether or not the operation is being executed asyncronously. + /// + public virtual bool Async { get; } + + /// + /// A timestamp from that can be used for timing. + /// + public virtual long Timestamp { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/CommandEndData.cs b/src/EFCore.Relational/Diagnostics/CommandEndData.cs new file mode 100644 index 00000000000..9b5e162c04a --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/CommandEndData.cs @@ -0,0 +1,60 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for + /// command end events. + /// + public class CommandEndData : CommandData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// The method. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// Indicates whether or not the command was executed asyncronously. + /// + /// + /// A timestamp from that can be used for timing. + /// + /// + /// The duration of execution as ticks from . + /// + public CommandEndData( + [NotNull] DbCommand command, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + bool async, + long timestamp, + long duration) + : base(command, executeMethod, commandId, connectionId, async, timestamp) + { + Duration = duration; + } + + /// + /// The duration of execution as ticks from . + /// + public virtual long Duration { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/CommandErrorData.cs b/src/EFCore.Relational/Diagnostics/CommandErrorData.cs new file mode 100644 index 00000000000..6450f57f7c9 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/CommandErrorData.cs @@ -0,0 +1,64 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for . + /// + public class CommandErrorData : CommandEndData + { + /// + /// Constructs the event payload. + /// + /// + /// The that was executing when it failed. + /// + /// + /// The method that was used to execute the command. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// The exception that was thrown when execution failed. + /// + /// + /// Indicates whether or not the command was executed asyncronously. + /// + /// + /// A timestamp from that can be used + /// with to time execution. + /// + /// + /// The duration of execution as ticks from . + /// + public CommandErrorData( + [NotNull] DbCommand command, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + [NotNull] Exception exception, + bool async, + long timestamp, + long duration) + : base(command, executeMethod, commandId, connectionId, async, timestamp, duration) + { + Exception = exception; + } + + /// + /// The exception that was thrown when execution failed. + /// + public virtual Exception Exception { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/CommandExecutedData.cs b/src/EFCore.Relational/Diagnostics/CommandExecutedData.cs new file mode 100644 index 00000000000..91c1dbfbf80 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/CommandExecutedData.cs @@ -0,0 +1,64 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for . + /// + public class CommandExecutedData : CommandEndData + { + /// + /// Constructs the event payload. + /// + /// + /// The that was executing when it failed. + /// + /// + /// The method that was used to execute the command. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// The result of executing the operation. + /// + /// + /// Indicates whether or not the command was executed asyncronously. + /// + /// + /// A timestamp from that can be used + /// with to time execution. + /// + /// + /// The duration of execution as ticks from . + /// + public CommandExecutedData( + [NotNull] DbCommand command, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + [CanBeNull] object result, + bool async, + long timestamp, + long duration) + : base(command, executeMethod, commandId, connectionId, async, timestamp, duration) + { + Result = result; + } + + /// + /// The result of executing the command. + /// + public virtual object Result { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/ConnectionData.cs b/src/EFCore.Relational/Diagnostics/ConnectionData.cs new file mode 100644 index 00000000000..b8a67d8a3b1 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/ConnectionData.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload base class for + /// connection events. + /// + public class ConnectionData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// Indicates whether or not the operation is happening asyncronously. + /// + /// + /// A timestamp from that can be used for timing. + /// + public ConnectionData( + [NotNull] DbConnection connection, + Guid connectionId, + bool async, + long timestamp) + { + Connection = connection; + ConnectionId = connectionId; + Async = async; + Timestamp = timestamp; + } + + /// + /// The . + /// + public virtual DbConnection Connection { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid ConnectionId { get; } + + /// + /// Indicates whether or not the operation is happening asyncronously. + /// + public virtual bool Async { get; } + + /// + /// A timestamp from that can be used for timing. + /// + public virtual long Timestamp { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/ConnectionEndData.cs b/src/EFCore.Relational/Diagnostics/ConnectionEndData.cs new file mode 100644 index 00000000000..2bda10921e5 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/ConnectionEndData.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload class for + /// connection ending events. + /// + public class ConnectionEndData : ConnectionData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// Indicates whether or not the operation is happening asyncronously. + /// + /// + /// A timestamp from that can be used for timing. + /// + /// + /// The duration of execution as ticks from . + /// + public ConnectionEndData( + [NotNull] DbConnection connection, + Guid connectionId, + bool async, + long timestamp, + long duration) + : base(connection, connectionId, async, timestamp) + { + Duration = duration; + } + + /// + /// The duration of execution as ticks from . + /// + public virtual long Duration { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/ConnectionErrorData.cs b/src/EFCore.Relational/Diagnostics/ConnectionErrorData.cs new file mode 100644 index 00000000000..1e10d66fc6c --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/ConnectionErrorData.cs @@ -0,0 +1,55 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for . + /// + public class ConnectionErrorData : ConnectionEndData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// The exception that was thrown when the connection failed. + /// + /// + /// Indicates whether or not the operation is happening asyncronously. + /// + /// + /// A timestamp from that can be used for timing. + /// + /// + /// The duration of execution as ticks from . + /// + public ConnectionErrorData( + [NotNull] DbConnection connection, + Guid connectionId, + [NotNull] Exception exception, + bool async, + long timestamp, + long duration) + : base(connection, connectionId, async, timestamp, duration) + { + Exception = exception; + } + + /// + /// The exception that was thrown when the connection failed. + /// + public virtual Exception Exception { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/DataReaderDisposingData.cs b/src/EFCore.Relational/Diagnostics/DataReaderDisposingData.cs new file mode 100644 index 00000000000..81a8a4cffa0 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/DataReaderDisposingData.cs @@ -0,0 +1,96 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// event payload for . + /// + public class DataReaderDisposingData + { + /// + /// Constructs a event payload for . + /// + /// + /// The that created the reader. + /// + /// + /// The that is being disposed. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + /// + /// + /// A timestamp from that can be used + /// with to time execution. + /// + /// + /// The duration of execution as ticks from . + /// + public DataReaderDisposingData( + [NotNull] DbCommand command, + [NotNull] DbDataReader dataReader, + Guid commandId, + Guid connectionId, + int recordsAffected, + long timestamp, + long duration) + { + Command = command; + DataReader = dataReader; + CommandId = commandId; + ConnectionId = connectionId; + RecordsAffected = recordsAffected; + Timestamp = timestamp; + Duration = duration; + } + + /// + /// The that created the reader. + /// + public virtual DbCommand Command { get; } + + /// + /// The that is being disposed. + /// + public virtual DbDataReader DataReader { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid CommandId { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid ConnectionId { get; } + + /// + /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + /// + public virtual int RecordsAffected { get; } + + /// + /// A timestamp from that can be used + /// with to time execution. + /// + public virtual long Timestamp { get; } + + /// + /// The duration of execution as ticks from . + /// + public virtual long Duration { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/DbCommandMethod.cs b/src/EFCore.Relational/Diagnostics/DbCommandMethod.cs new file mode 100644 index 00000000000..be2c5b4e98d --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/DbCommandMethod.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Data.Common; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// Enum used by , an subclasses to indicate the + /// method on + /// being used to execute the command. + /// + public enum DbCommandMethod + { + /// + /// The or + /// method. + /// + ExecuteNonQuery, + + /// + /// The or + /// method. + /// + ExecuteScalar, + + /// + /// The or + /// method. + /// + ExecuteReader + } +} diff --git a/src/EFCore.Relational/Diagnostics/MigrationData.cs b/src/EFCore.Relational/Diagnostics/MigrationData.cs new file mode 100644 index 00000000000..79a0b5567c5 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/MigrationData.cs @@ -0,0 +1,39 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for + /// events of a specific migration. + /// + public class MigrationData : MigratorData + { + /// + /// Constructs the event payload. + /// + /// + /// The in use. + /// + /// + /// The being processed. + /// + public MigrationData( + [NotNull] IMigrator migrator, + [NotNull] Migration migration) + : base(migrator) + { + Migration = migration; + } + + /// + /// The being processed. + /// + public virtual Migration Migration { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/MigrationScriptingData.cs b/src/EFCore.Relational/Diagnostics/MigrationScriptingData.cs new file mode 100644 index 00000000000..1bc829e8a3d --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/MigrationScriptingData.cs @@ -0,0 +1,63 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for + /// migration scripting events. + /// + public class MigrationScriptingData : MigrationData + { + /// + /// Constructs the event payload. + /// + /// + /// The in use. + /// + /// + /// The being processed. + /// + /// + /// The migration that scripting is starting from. + /// + /// + /// The migration that scripting is going to. + /// + /// + /// Indicates whether or not the script is idempotent. + /// + public MigrationScriptingData( + [NotNull] IMigrator migrator, + [NotNull] Migration migration, + [CanBeNull] string fromMigration, + [CanBeNull] string toMigration, + bool idempotent) + : base(migrator, migration) + { + FromMigration = fromMigration; + ToMigration = toMigration; + Idempotent = idempotent; + } + + /// + /// The migration that scripting is starting from. + /// + public virtual string FromMigration { get; } + + /// + /// The migration that scripting is going to. + /// + public virtual string ToMigration { get; } + + /// + /// Indicates whether or not the script is idempotent. + /// + public virtual bool Idempotent { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/MigratorConnectionData.cs b/src/EFCore.Relational/Diagnostics/MigratorConnectionData.cs new file mode 100644 index 00000000000..2f6ca056e89 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/MigratorConnectionData.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for + /// migration connection events. + /// + public class MigratorConnectionData : MigratorData + { + /// + /// Constructs the event payload. + /// + /// + /// The in use. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the instance being used. + /// + public MigratorConnectionData( + [NotNull] IMigrator migrator, + [NotNull] DbConnection connection, + Guid connectionId) + : base(migrator) + { + Connection = connection; + ConnectionId = connectionId; + } + + /// + /// The . + /// + public virtual DbConnection Connection { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid ConnectionId { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/MigratorData.cs b/src/EFCore.Relational/Diagnostics/MigratorData.cs new file mode 100644 index 00000000000..860d68878c1 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/MigratorData.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for + /// migration events. + /// + public class MigratorData + { + /// + /// Constructs the event payload. + /// + /// + /// The in use. + /// + public MigratorData([NotNull] IMigrator migrator) + { + Migrator = migrator; + } + + /// + /// The in use. + /// + public virtual IMigrator Migrator { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/TransactionData.cs b/src/EFCore.Relational/Diagnostics/TransactionData.cs new file mode 100644 index 00000000000..9abb8d4ac80 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/TransactionData.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload base class for + /// transaction events. + /// + public class TransactionData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the Entity Framework transaction being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A timestamp from that can be used for timing. + /// + public TransactionData( + [NotNull] DbTransaction transaction, + Guid transactionId, + Guid connectionId, + long timestamp) + { + Transaction = transaction; + TransactionId = transactionId; + ConnectionId = connectionId; + Timestamp = timestamp; + } + + /// + /// The . + /// + public virtual DbTransaction Transaction { get; } + + /// + /// A correlation ID that identifies the Entity Framework transaction being used. + /// + public virtual Guid TransactionId { get; } + + /// + /// A correlation ID that identifies the instance being used. + /// + public virtual Guid ConnectionId { get; } + + /// + /// A timestamp from that can be used for timing. + /// + public virtual long Timestamp { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/TransactionEndData.cs b/src/EFCore.Relational/Diagnostics/TransactionEndData.cs new file mode 100644 index 00000000000..261216b3a1c --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/TransactionEndData.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload base class for + /// transaction end events. + /// + public class TransactionEndData : TransactionData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the Entity Framework transaction being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// A timestamp from that can be used for timing. + /// + /// + /// The duration of execution as ticks from . + /// + public TransactionEndData( + [NotNull] DbTransaction transaction, + Guid transactionId, + Guid connectionId, + long timestamp, + long duration) + : base(transaction, transactionId, connectionId, timestamp) + { + Duration = duration; + } + + /// + /// The duration of execution as ticks from . + /// + public virtual long Duration { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/TransactionErrorData.cs b/src/EFCore.Relational/Diagnostics/TransactionErrorData.cs new file mode 100644 index 00000000000..2b93f4a4949 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/TransactionErrorData.cs @@ -0,0 +1,63 @@ +using System; +using System.Data.Common; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload base class for + /// transaction error events. + /// + public class TransactionErrorData : TransactionEndData + { + /// + /// Constructs the event payload. + /// + /// + /// The . + /// + /// + /// A correlation ID that identifies the Entity Framework transaction being used. + /// + /// + /// A correlation ID that identifies the instance being used. + /// + /// + /// One of "Commit" or "Rollback". + /// + /// + /// The exception that was thrown when the transaction failed. + /// + /// + /// A timestamp from that can be used for timing. + /// + /// + /// The duration of execution as ticks from . + /// + public TransactionErrorData( + [NotNull] DbTransaction transaction, + Guid transactionId, + Guid connectionId, + [NotNull] string action, + [NotNull] Exception exception, + long timestamp, + long duration) + : base(transaction, transactionId, connectionId, timestamp, duration) + { + Action = action; + Exception = exception; + } + + /// + /// One of "Commit" or "Rollback". + /// + public virtual string Action { get; } + + /// + /// The exception that was thrown when the transaction failed. + /// + public virtual Exception Exception { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Relational/Infrastructure/RelationalEventId.cs b/src/EFCore.Relational/Infrastructure/RelationalEventId.cs index d9d7102aa56..356886440ee 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalEventId.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalEventId.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Diagnostics; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; namespace Microsoft.EntityFrameworkCore.Infrastructure @@ -59,39 +60,74 @@ private enum Id QueryPossibleUnintendedUseOfEqualsWarning, // Model validation events - ModelValidationKeyDefaultValueWarning = CoreEventId.RelationalBaseId + 600, + ModelValidationKeyDefaultValueWarning = CoreEventId.RelationalBaseId + 600 } private static readonly string _connectionPrefix = LoggerCategory.Database.Connection.Name + "."; private static EventId MakeConnectionId(Id id) => new EventId((int)id, _connectionPrefix + id); /// - /// A database connection is opening. - /// This event is in the category. + /// + /// A database connection is opening. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ConnectionOpening = MakeConnectionId(Id.ConnectionOpening); /// - /// A database connection has been opened. - /// This event is in the category. + /// + /// A database connection has been opened. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ConnectionOpened = MakeConnectionId(Id.ConnectionOpened); /// - /// A database connection is closing. - /// This event is in the category. + /// + /// A database connection is closing. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ConnectionClosing = MakeConnectionId(Id.ConnectionClosing); /// - /// A database connection has been closed. - /// This event is in the category. + /// + /// A database connection has been closed. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ConnectionClosed = MakeConnectionId(Id.ConnectionClosed); /// - /// A error occurred while opening or using a database connection. - /// This event is in the category. + /// + /// A error occurred while opening or using a database connection. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ConnectionError = MakeConnectionId(Id.ConnectionError); @@ -99,20 +135,41 @@ private enum Id private static EventId MakeCommandId(Id id) => new EventId((int)id, _sqlPrefix + id); /// - /// A database command is executing. - /// This event is in the category. + /// + /// A database command is executing. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId CommandExecuting = MakeCommandId(Id.CommandExecuting); /// - /// A database command has been executed. - /// This event is in the category. + /// + /// A database command has been executed. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId CommandExecuted = MakeCommandId(Id.CommandExecuted); /// - /// An error occurred while a database command was executing. - /// This event is in the category. + /// + /// An error occurred while a database command was executing. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId CommandError = MakeCommandId(Id.CommandError); @@ -120,44 +177,93 @@ private enum Id private static EventId MakeTransactionId(Id id) => new EventId((int)id, _transactionPrefix + id); /// - /// A database transaction has been started. - /// This event is in the category. + /// + /// A database transaction has been started. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionStarted = MakeTransactionId(Id.TransactionStarted); /// - /// Entity Framework started using an already existing database transaction. - /// This event is in the category. + /// + /// Entity Framework started using an already existing database transaction. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionUsed = MakeTransactionId(Id.TransactionUsed); /// - /// A database transaction has been committed. - /// This event is in the category. + /// + /// A database transaction has been committed. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionCommitted = MakeTransactionId(Id.TransactionCommitted); /// - /// A database transaction has been rolled back. - /// This event is in the category. + /// + /// A database transaction has been rolled back. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionRolledBack = MakeTransactionId(Id.TransactionRolledBack); /// - /// A database transaction has been disposed. - /// This event is in the category. + /// + /// A database transaction has been disposed. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionDisposed = MakeTransactionId(Id.TransactionDisposed); /// - /// An error has occurred while using. committing, or rolling back a database transaction. - /// This event is in the category. + /// + /// An error has occurred while using. committing, or rolling back a database transaction. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionError = MakeTransactionId(Id.TransactionError); /// - /// An application may have expected an ambient transaction to be used when it was actually ignorred. - /// This event is in the category. + /// + /// An application may have expected an ambient transaction to be used when it was actually ignorred. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId AmbientTransactionWarning = MakeTransactionId(Id.AmbientTransactionWarning); @@ -165,8 +271,15 @@ private enum Id private static EventId MakeReaderId(Id id) => new EventId((int)id, _dataReaderPrefix + id); /// - /// A database data reader has been disposed. - /// This event is in the category. + /// + /// A database data reader has been disposed. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId DataReaderDisposing = MakeReaderId(Id.DataReaderDisposing); @@ -174,32 +287,67 @@ private enum Id private static EventId MakeMigrationsId(Id id) => new EventId((int)id, _migrationsPrefix + id); /// - /// Migrations is using a database connection. - /// This event is in the category. + /// + /// Migrations is using a database connection. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrateUsingConnection = MakeMigrationsId(Id.MigrateUsingConnection); /// - /// A migration is being reverted. - /// This event is in the category. + /// + /// A migration is being reverted. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationReverting = MakeMigrationsId(Id.MigrationReverting); /// - /// A migration is being applied. - /// This event is in the category. + /// + /// A migration is being applied. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationApplying = MakeMigrationsId(Id.MigrationApplying); /// - /// Migrations is generating a "down" script. - /// This event is in the category. + /// + /// Migrations is generating a "down" script. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationGeneratingDownScript = MakeMigrationsId(Id.MigrationGeneratingDownScript); /// - /// Migrations is generating an "up" script. - /// This event is in the category. + /// + /// Migrations is generating an "up" script. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationGeneratingUpScript = MakeMigrationsId(Id.MigrationGeneratingUpScript); @@ -207,14 +355,22 @@ private enum Id private static EventId MakeQueryId(Id id) => new EventId((int)id, _queryPrefix + id); /// - /// Part of a query is being evaluated on the client instead of on the database server. - /// This event is in the category. + /// + /// Part of a query is being evaluated on the client instead of on the database server. + /// + /// + /// This event is in the category. + /// /// public static readonly EventId QueryClientEvaluationWarning = MakeQueryId(Id.QueryClientEvaluationWarning); /// - /// A query is using equals comparisons in a possibly unintended way. - /// This event is in the category. + /// + /// A query is using equals comparisons in a possibly unintended way. + /// + /// + /// This event is in the category. + /// /// public static readonly EventId QueryPossibleUnintendedUseOfEqualsWarning = MakeQueryId(Id.QueryPossibleUnintendedUseOfEqualsWarning); @@ -222,8 +378,12 @@ private enum Id private static EventId MakeValidationId(Id id) => new EventId((int)id, _validationPrefix + id); /// - /// A single database default column value has been set on a key column. - /// This event is in the category. + /// + /// A single database default column value has been set on a key column. + /// + /// + /// This event is in the category. + /// /// public static readonly EventId ModelValidationKeyDefaultValueWarning = MakeValidationId(Id.ModelValidationKeyDefaultValueWarning); } diff --git a/src/EFCore.Relational/Internal/RelationalDiagnosticSourceAfterMessage.cs b/src/EFCore.Relational/Internal/RelationalDiagnosticSourceAfterMessage.cs deleted file mode 100644 index 3d13467894e..00000000000 --- a/src/EFCore.Relational/Internal/RelationalDiagnosticSourceAfterMessage.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Data.Common; - -namespace Microsoft.EntityFrameworkCore.Internal -{ - // TODO revert to anonymous types when https://github.com/dotnet/corefx/issues/4672 is fixed - internal class RelationalDiagnosticSourceAfterMessage - { - public Guid ConnectionId { get; set; } - public DbCommand Command { get; set; } - public string ExecuteMethod { get; set; } - public object Result { get; set; } - public bool IsAsync { get; set; } - public Guid InstanceId { get; set; } - public long Timestamp { get; set; } - public long Duration { get; set; } - public Exception Exception { get; set; } - } -} diff --git a/src/EFCore.Relational/Internal/RelationalDiagnosticSourceBeforeMessage.cs b/src/EFCore.Relational/Internal/RelationalDiagnosticSourceBeforeMessage.cs deleted file mode 100644 index 9f5ae970500..00000000000 --- a/src/EFCore.Relational/Internal/RelationalDiagnosticSourceBeforeMessage.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Data.Common; - -namespace Microsoft.EntityFrameworkCore.Internal -{ - // TODO revert to anonymous types when https://github.com/dotnet/corefx/issues/4672 is fixed - internal class RelationalDiagnosticSourceBeforeMessage - { - public Guid ConnectionId { get; set; } - public DbCommand Command { get; set; } - public string ExecuteMethod { get; set; } - public bool IsAsync { get; set; } - public Guid InstanceId { get; set; } - public long Timestamp { get; set; } - } -} diff --git a/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs b/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs index fa5b18ce3f0..c86100e3c4a 100644 --- a/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs +++ b/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Linq.Expressions; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -31,13 +32,13 @@ public static class RelationalLoggerExtensions /// directly from your code. This API may change or be removed in future releases. /// public static void CommandExecuting( - [NotNull] this IDiagnosticsLogger diagnostics, - Guid connectionId, + [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] DbCommand command, - [NotNull] string executeMethod, - Guid instanceId, - long startTimestamp, - bool async) + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + bool async, + long startTimestamp) { var eventId = RelationalEventId.CommandExecuting; @@ -62,15 +63,13 @@ public static void CommandExecuting( { diagnostics.DiagnosticSource.Write( eventId.Name, - new RelationalDiagnosticSourceBeforeMessage - { - ConnectionId = connectionId, - Command = command, - ExecuteMethod = executeMethod, - InstanceId = instanceId, - Timestamp = startTimestamp, - IsAsync = async - }); + new CommandData( + command, + executeMethod, + commandId, + connectionId, + async, + startTimestamp)); } } @@ -80,14 +79,14 @@ public static void CommandExecuting( /// public static void CommandExecuted( [NotNull] this IDiagnosticsLogger diagnostics, - Guid connectionId, [NotNull] DbCommand command, - [NotNull] string executeMethod, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, [CanBeNull] object methodResult, - Guid instanceId, + bool async, long startTimestamp, - long currentTimestamp, - bool async = false) + long currentTimestamp) { var eventId = RelationalEventId.CommandExecuted; @@ -115,17 +114,15 @@ public static void CommandExecuted( { diagnostics.DiagnosticSource.Write( eventId.Name, - new RelationalDiagnosticSourceAfterMessage - { - ConnectionId = connectionId, - Command = command, - ExecuteMethod = executeMethod, - Result = methodResult, - InstanceId = instanceId, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp, - IsAsync = async - }); + new CommandExecutedData( + command, + executeMethod, + commandId, + connectionId, + methodResult, + async, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -135,14 +132,14 @@ public static void CommandExecuted( /// public static void CommandError( [NotNull] this IDiagnosticsLogger diagnostics, - Guid connectionId, [NotNull] DbCommand command, - [NotNull] string executeMethod, - Guid instanceId, - long startTimestamp, - long currentTimestamp, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, [NotNull] Exception exception, - bool async) + bool async, + long startTimestamp, + long currentTimestamp) { var eventId = RelationalEventId.CommandError; @@ -170,17 +167,15 @@ public static void CommandError( { diagnostics.DiagnosticSource.Write( eventId.Name, - new RelationalDiagnosticSourceAfterMessage - { - ConnectionId = connectionId, - Command = command, - ExecuteMethod = executeMethod, - InstanceId = instanceId, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp, - Exception = exception, - IsAsync = async - }); + new CommandErrorData( + command, + executeMethod, + commandId, + connectionId, + exception, + async, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -232,7 +227,6 @@ var logParameterValues public static void ConnectionOpening( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - Guid instanceId, long startTimestamp, bool async) { @@ -243,21 +237,19 @@ public static void ConnectionOpening( diagnostics.Logger.LogDebug( eventId, RelationalStrings.RelationalLoggerOpeningConnection( - connection.DbConnection.Database, + connection.DbConnection.Database, connection.DbConnection.DataSource)); } if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - InstanceId = instanceId, - Timestamp = startTimestamp, - IsAsync = async - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new ConnectionData( + connection.DbConnection, + connection.ConnectionId, + async, + startTimestamp)); } } @@ -268,7 +260,6 @@ public static void ConnectionOpening( public static void ConnectionOpened( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - Guid instanceId, long startTimestamp, long currentTimestamp, bool async) @@ -283,19 +274,17 @@ public static void ConnectionOpened( connection.DbConnection.Database, connection.DbConnection.DataSource)); } - + if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - InstanceId = instanceId, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp, - IsAsync = async - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new ConnectionEndData( + connection.DbConnection, + connection.ConnectionId, + async, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -306,9 +295,7 @@ public static void ConnectionOpened( public static void ConnectionClosing( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - Guid instanceId, - long startTimestamp, - bool async) + long startTimestamp) { var eventId = RelationalEventId.ConnectionClosing; @@ -323,15 +310,13 @@ public static void ConnectionClosing( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - InstanceId = instanceId, - Timestamp = startTimestamp, - IsAsync = async - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new ConnectionData( + connection.DbConnection, + connection.ConnectionId, + false, + startTimestamp)); } } @@ -342,10 +327,8 @@ public static void ConnectionClosing( public static void ConnectionClosed( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - Guid instanceId, long startTimestamp, - long currentTimestamp, - bool async) + long currentTimestamp) { var eventId = RelationalEventId.ConnectionClosed; @@ -360,16 +343,14 @@ public static void ConnectionClosed( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - InstanceId = instanceId, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp, - IsAsync = async - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new ConnectionEndData( + connection.DbConnection, + connection.ConnectionId, + false, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -381,7 +362,6 @@ public static void ConnectionError( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, [NotNull] Exception exception, - Guid instanceId, long startTimestamp, long currentTimestamp, bool async) @@ -400,17 +380,15 @@ public static void ConnectionError( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Exception = exception, - InstanceId = instanceId, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp, - IsAsync = async - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new ConnectionErrorData( + connection.DbConnection, + connection.ConnectionId, + exception, + async, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -421,7 +399,9 @@ public static void ConnectionError( public static void TransactionStarted( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - [NotNull] DbTransaction transaction) + [NotNull] DbTransaction transaction, + Guid transactionId, + long timestamp) { var eventId = RelationalEventId.TransactionStarted; @@ -434,13 +414,13 @@ public static void TransactionStarted( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Transaction = transaction - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new TransactionData( + transaction, + transactionId, + connection.ConnectionId, + timestamp)); } } @@ -451,7 +431,9 @@ public static void TransactionStarted( public static void TransactionUsed( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - [NotNull] DbTransaction transaction) + [NotNull] DbTransaction transaction, + Guid transactionId, + long timestamp) { var eventId = RelationalEventId.TransactionUsed; @@ -464,13 +446,13 @@ public static void TransactionUsed( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Transaction = transaction - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new TransactionData( + transaction, + transactionId, + connection.ConnectionId, + timestamp)); } } @@ -482,6 +464,7 @@ public static void TransactionCommitted( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, [NotNull] DbTransaction transaction, + Guid transactionId, long startTimestamp, long currentTimestamp) { @@ -496,15 +479,14 @@ public static void TransactionCommitted( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Transaction = transaction, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new TransactionEndData( + transaction, + transactionId, + connection.ConnectionId, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -516,6 +498,7 @@ public static void TransactionRolledBack( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, [NotNull] DbTransaction transaction, + Guid transactionId, long startTimestamp, long currentTimestamp) { @@ -530,15 +513,14 @@ public static void TransactionRolledBack( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Transaction = transaction, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new TransactionEndData( + transaction, + transactionId, + connection.ConnectionId, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -549,7 +531,9 @@ public static void TransactionRolledBack( public static void TransactionDisposed( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, - [NotNull] DbTransaction transaction) + [NotNull] DbTransaction transaction, + Guid transactionId, + long timestamp) { var eventId = RelationalEventId.TransactionDisposed; @@ -562,13 +546,13 @@ public static void TransactionDisposed( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Transaction = transaction - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new TransactionData( + transaction, + transactionId, + connection.ConnectionId, + timestamp)); } } @@ -580,6 +564,7 @@ public static void TransactionError( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, [NotNull] DbTransaction transaction, + Guid transactionId, [NotNull] string action, [NotNull] Exception exception, long startTimestamp, @@ -597,16 +582,16 @@ public static void TransactionError( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - Transaction = transaction, - Exception = exception, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new TransactionErrorData( + transaction, + connection.ConnectionId, + transactionId, + action, + exception, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -616,7 +601,8 @@ public static void TransactionError( /// public static void AmbientTransactionWarning( [NotNull] this IDiagnosticsLogger diagnostics, - [NotNull] IRelationalConnection connection) + [NotNull] IRelationalConnection connection, + long timestamp) { var eventId = RelationalEventId.AmbientTransactionWarning; @@ -629,12 +615,13 @@ public static void AmbientTransactionWarning( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new ConnectionData( + connection.DbConnection, + connection.ConnectionId, + false, + timestamp)); } } @@ -645,7 +632,9 @@ public static void AmbientTransactionWarning( public static void DataReaderDisposing( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IRelationalConnection connection, + [NotNull] DbCommand command, [NotNull] DbDataReader dataReader, + Guid commandId, int recordsAffected, long startTimestamp, long currentTimestamp) @@ -658,19 +647,19 @@ public static void DataReaderDisposing( eventId, RelationalStrings.DisposingDataReader); } - + if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - DataReader = dataReader, - RecordsAffected = recordsAffected, - Timestamp = currentTimestamp, - Duration = currentTimestamp - startTimestamp - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new DataReaderDisposingData( + command, + dataReader, + commandId, + connection.ConnectionId, + recordsAffected, + currentTimestamp, + currentTimestamp - startTimestamp)); } } @@ -681,8 +670,7 @@ public static void DataReaderDisposing( public static void MigrateUsingConnection( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IMigrator migrator, - [NotNull] IRelationalConnection connection, - [CanBeNull] string targetMigration) + [NotNull] IRelationalConnection connection) { var eventId = RelationalEventId.MigrateUsingConnection; @@ -696,14 +684,12 @@ public static void MigrateUsingConnection( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Migrator = migrator, - Connection = connection.DbConnection, - ConnectionId = connection.ConnectionId, - TargetMigration = targetMigration - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new MigratorConnectionData( + migrator, + connection.DbConnection, + connection.ConnectionId)); } } @@ -714,8 +700,7 @@ public static void MigrateUsingConnection( public static void MigrationReverting( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IMigrator migrator, - [NotNull] Migration migration, - [CanBeNull] string targetMigration) + [NotNull] Migration migration) { var eventId = RelationalEventId.MigrationReverting; @@ -728,13 +713,11 @@ public static void MigrationReverting( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Migrator = migrator, - Migration = migration, - TargetMigration = targetMigration - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new MigrationData( + migrator, + migration)); } } @@ -745,8 +728,7 @@ public static void MigrationReverting( public static void MigrationApplying( [NotNull] this IDiagnosticsLogger diagnostics, [NotNull] IMigrator migrator, - [NotNull] Migration migration, - [CanBeNull] string targetMigration) + [NotNull] Migration migration) { var eventId = RelationalEventId.MigrationApplying; @@ -759,13 +741,11 @@ public static void MigrationApplying( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Migrator = migrator, - Migration = migration, - TargetMigration = targetMigration - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new MigrationData( + migrator, + migration)); } } @@ -792,15 +772,14 @@ public static void MigrationGeneratingDownScript( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Migrator = migrator, - Migration = migration, - FromMigration= fromMigration, - ToMigration = toMigration, - Idempotent = idempotent - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new MigrationScriptingData( + migrator, + migration, + fromMigration, + toMigration, + idempotent)); } } @@ -827,15 +806,14 @@ public static void MigrationGeneratingUpScript( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, - new - { - Migrator = migrator, - Migration = migration, - FromMigration = fromMigration, - ToMigration = toMigration, - Idempotent = idempotent - }); + diagnostics.DiagnosticSource.Write( + eventId.Name, + new MigrationScriptingData( + migrator, + migration, + fromMigration, + toMigration, + idempotent)); } } @@ -859,7 +837,8 @@ public static void QueryClientEvaluationWarning( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, + diagnostics.DiagnosticSource.Write( + eventId.Name, new { QueryModel = queryModel, @@ -890,7 +869,8 @@ public static void QueryPossibleUnintendedUseOfEqualsWarning( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, + diagnostics.DiagnosticSource.Write( + eventId.Name, new { MethodCallExpression = methodCallExpression, @@ -918,7 +898,8 @@ public static void ModelValidationKeyDefaultValueWarning( if (diagnostics.DiagnosticSource.IsEnabled(eventId.Name)) { - diagnostics.DiagnosticSource.Write(eventId.Name, + diagnostics.DiagnosticSource.Write( + eventId.Name, new { Property = property @@ -926,7 +907,7 @@ public static void ModelValidationKeyDefaultValueWarning( } } - private static readonly double _timestampToMilliseconds + private static readonly double _timestampToMilliseconds = (double)TimeSpan.TicksPerSecond / (Stopwatch.Frequency * TimeSpan.TicksPerMillisecond); private static long DeriveTimespan(long startTimestamp, long currentTimestamp) diff --git a/src/EFCore.Relational/Migrations/Internal/Migrator.cs b/src/EFCore.Relational/Migrations/Internal/Migrator.cs index 6e86ae19372..5df0336181d 100644 --- a/src/EFCore.Relational/Migrations/Internal/Migrator.cs +++ b/src/EFCore.Relational/Migrations/Internal/Migrator.cs @@ -77,7 +77,7 @@ public Migrator( /// public virtual void Migrate(string targetMigration = null) { - _logger.MigrateUsingConnection(this, _connection, targetMigration); + _logger.MigrateUsingConnection(this, _connection); if (!_historyRepository.Exists()) { @@ -106,7 +106,7 @@ public virtual async Task MigrateAsync( string targetMigration = null, CancellationToken cancellationToken = default(CancellationToken)) { - _logger.MigrateUsingConnection(this, _connection, targetMigration); + _logger.MigrateUsingConnection(this, _connection); if (!await _historyRepository.ExistsAsync(cancellationToken)) { @@ -134,12 +134,11 @@ private IEnumerable>> GetMigrationCommandLi IReadOnlyList appliedMigrationEntries, string targetMigration = null) { - IReadOnlyList migrationsToApply, migrationsToRevert; PopulateMigrations( appliedMigrationEntries.Select(t => t.MigrationId), targetMigration, - out migrationsToApply, - out migrationsToRevert); + out var migrationsToApply, + out var migrationsToRevert); for (var i = 0; i < migrationsToRevert.Count; i++) { @@ -148,7 +147,7 @@ private IEnumerable>> GetMigrationCommandLi var index = i; yield return () => { - _logger.MigrationReverting(this, migration, targetMigration); + _logger.MigrationReverting(this, migration); return GenerateDownSql( migration, @@ -162,7 +161,7 @@ private IEnumerable>> GetMigrationCommandLi { yield return () => { - _logger.MigrationApplying(this, migration, targetMigration); + _logger.MigrationApplying(this, migration); return GenerateUpSql(migration); }; @@ -242,12 +241,11 @@ public virtual string GenerateScript( .Select(t => t.Key); } - IReadOnlyList migrationsToApply, migrationsToRevert; PopulateMigrations( appliedMigrations, toMigration, - out migrationsToApply, - out migrationsToRevert); + out var migrationsToApply, + out var migrationsToRevert); var builder = new IndentedStringBuilder(); diff --git a/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs b/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs index b071e5fa9d0..a932ea31b5d 100644 --- a/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs +++ b/src/EFCore.Relational/Storage/Internal/RelationalCommand.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Utilities; @@ -74,7 +75,7 @@ public virtual int ExecuteNonQuery( IReadOnlyDictionary parameterValues) => (int)Execute( Check.NotNull(connection, nameof(connection)), - nameof(ExecuteNonQuery), + DbCommandMethod.ExecuteNonQuery, parameterValues); int IRelationalCommand.ExecuteNonQuery( @@ -91,7 +92,7 @@ public virtual Task ExecuteNonQueryAsync( CancellationToken cancellationToken = default(CancellationToken)) => ExecuteAsync( Check.NotNull(connection, nameof(connection)), - nameof(ExecuteNonQuery), + DbCommandMethod.ExecuteNonQuery, parameterValues, cancellationToken: cancellationToken).Cast(); @@ -108,7 +109,7 @@ public virtual object ExecuteScalar( IReadOnlyDictionary parameterValues) => Execute( Check.NotNull(connection, nameof(connection)), - nameof(ExecuteScalar), + DbCommandMethod.ExecuteScalar, parameterValues); object IRelationalCommand.ExecuteScalar(IRelationalConnection connection, IReadOnlyDictionary parameterValues, bool manageConnection) @@ -124,7 +125,7 @@ public virtual Task ExecuteScalarAsync( CancellationToken cancellationToken = default(CancellationToken)) => ExecuteAsync( Check.NotNull(connection, nameof(connection)), - nameof(ExecuteScalar), + DbCommandMethod.ExecuteScalar, parameterValues, cancellationToken: cancellationToken); @@ -141,7 +142,7 @@ public virtual RelationalDataReader ExecuteReader( IReadOnlyDictionary parameterValues) => (RelationalDataReader)Execute( Check.NotNull(connection, nameof(connection)), - nameof(ExecuteReader), + DbCommandMethod.ExecuteReader, parameterValues, closeConnection: false); @@ -159,7 +160,7 @@ public virtual Task ExecuteReaderAsync( CancellationToken cancellationToken = default(CancellationToken)) => ExecuteAsync( Check.NotNull(connection, nameof(connection)), - nameof(ExecuteReader), + DbCommandMethod.ExecuteReader, parameterValues, closeConnection: false, cancellationToken: cancellationToken).Cast(); @@ -174,34 +175,33 @@ Task IRelationalCommand.ExecuteReaderAsync( /// protected virtual object Execute( [NotNull] IRelationalConnection connection, - [NotNull] string executeMethod, + DbCommandMethod executeMethod, [CanBeNull] IReadOnlyDictionary parameterValues, bool closeConnection = true) { Check.NotNull(connection, nameof(connection)); - Check.NotEmpty(executeMethod, nameof(executeMethod)); var dbCommand = CreateCommand(connection, parameterValues); connection.Open(); var startTimestamp = Stopwatch.GetTimestamp(); - var instanceId = Guid.NewGuid(); + var commandId = Guid.NewGuid(); SqlLogger.CommandExecuting( - connection.ConnectionId, dbCommand, executeMethod, - instanceId, - startTimestamp, - async: false); + commandId, + connection.ConnectionId, + async: false, + startTimestamp: startTimestamp); object result; try { switch (executeMethod) { - case nameof(ExecuteNonQuery): + case DbCommandMethod.ExecuteNonQuery: { using (dbCommand) { @@ -210,7 +210,7 @@ protected virtual object Execute( break; } - case nameof(ExecuteScalar): + case DbCommandMethod.ExecuteScalar: { using (dbCommand) { @@ -219,7 +219,7 @@ protected virtual object Execute( break; } - case nameof(ExecuteReader): + case DbCommandMethod.ExecuteReader: { try { @@ -228,6 +228,7 @@ protected virtual object Execute( connection, dbCommand, dbCommand.ExecuteReader(), + commandId, ReaderLogger); } catch @@ -248,11 +249,12 @@ protected virtual object Execute( var currentTimestamp = Stopwatch.GetTimestamp(); SqlLogger.CommandExecuted( - connection.ConnectionId, dbCommand, executeMethod, + commandId, + connection.ConnectionId, result, - instanceId, + false, startTimestamp, currentTimestamp); @@ -266,14 +268,14 @@ protected virtual object Execute( var currentTimestamp = Stopwatch.GetTimestamp(); SqlLogger.CommandError( - connection.ConnectionId, dbCommand, executeMethod, - instanceId, - startTimestamp, - currentTimestamp, + commandId, + connection.ConnectionId, exception, - async: false); + false, + startTimestamp, + currentTimestamp); connection.Close(); @@ -293,35 +295,34 @@ protected virtual object Execute( /// protected virtual async Task ExecuteAsync( [NotNull] IRelationalConnection connection, - [NotNull] string executeMethod, + DbCommandMethod executeMethod, [CanBeNull] IReadOnlyDictionary parameterValues, bool closeConnection = true, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); - Check.NotEmpty(executeMethod, nameof(executeMethod)); var dbCommand = CreateCommand(connection, parameterValues); await connection.OpenAsync(cancellationToken); var startTimestamp = Stopwatch.GetTimestamp(); - var instanceId = Guid.NewGuid(); + var commandId = Guid.NewGuid(); SqlLogger.CommandExecuting( - connection.ConnectionId, dbCommand, executeMethod, - instanceId, - startTimestamp, - async: true); + commandId, + connection.ConnectionId, + async: true, + startTimestamp: startTimestamp); object result; try { switch (executeMethod) { - case nameof(ExecuteNonQuery): + case DbCommandMethod.ExecuteNonQuery: { using (dbCommand) { @@ -330,7 +331,7 @@ protected virtual async Task ExecuteAsync( break; } - case nameof(ExecuteScalar): + case DbCommandMethod.ExecuteScalar: { using (dbCommand) { @@ -339,7 +340,7 @@ protected virtual async Task ExecuteAsync( break; } - case nameof(ExecuteReader): + case DbCommandMethod.ExecuteReader: { try { @@ -347,6 +348,7 @@ protected virtual async Task ExecuteAsync( connection, dbCommand, await dbCommand.ExecuteReaderAsync(cancellationToken), + commandId, ReaderLogger); } catch @@ -367,14 +369,14 @@ await dbCommand.ExecuteReaderAsync(cancellationToken), var currentTimestamp = Stopwatch.GetTimestamp(); SqlLogger.CommandExecuted( - connection.ConnectionId, dbCommand, executeMethod, + commandId, + connection.ConnectionId, result, - instanceId, + true, startTimestamp, - currentTimestamp, - async: true); + currentTimestamp); if (closeConnection) { @@ -386,14 +388,14 @@ await dbCommand.ExecuteReaderAsync(cancellationToken), var currentTimestamp = Stopwatch.GetTimestamp(); SqlLogger.CommandError( - connection.ConnectionId, dbCommand, executeMethod, - instanceId, - startTimestamp, - currentTimestamp, + commandId, + connection.ConnectionId, exception, - async: true); + true, + startTimestamp, + currentTimestamp); connection.Close(); @@ -436,9 +438,7 @@ private DbCommand CreateCommand( foreach (var parameter in Parameters) { - object parameterValue; - - if (parameterValues.TryGetValue(parameter.InvariantName, out parameterValue)) + if (parameterValues.TryGetValue(parameter.InvariantName, out object parameterValue)) { parameter.AddDbParameter(command, parameterValue); } diff --git a/src/EFCore.Relational/Storage/RelationalConnection.cs b/src/EFCore.Relational/Storage/RelationalConnection.cs index cf489eb5b84..a657d3bda23 100644 --- a/src/EFCore.Relational/Storage/RelationalConnection.cs +++ b/src/EFCore.Relational/Storage/RelationalConnection.cs @@ -197,7 +197,11 @@ private IDbContextTransaction BeginTransactionWithNoPreconditions(IsolationLevel Dependencies.TransactionLogger, transactionOwned: true); - Dependencies.TransactionLogger.TransactionStarted(this, dbTransaction); + Dependencies.TransactionLogger.TransactionStarted( + this, + dbTransaction, + CurrentTransaction.TransactionId, + Stopwatch.GetTimestamp()); return CurrentTransaction; } @@ -230,7 +234,11 @@ public virtual IDbContextTransaction UseTransaction(DbTransaction transaction) Dependencies.TransactionLogger, transactionOwned: false); - Dependencies.TransactionLogger.TransactionUsed(this, transaction); + Dependencies.TransactionLogger.TransactionUsed( + this, + transaction, + CurrentTransaction.TransactionId, + Stopwatch.GetTimestamp()); } return CurrentTransaction; @@ -280,10 +288,8 @@ public virtual bool Open() if (_connection.Value.State != ConnectionState.Open) { var startTimestamp = Stopwatch.GetTimestamp(); - var instanceId = Guid.NewGuid(); Dependencies.ConnectionLogger.ConnectionOpening( this, - instanceId, startTimestamp, async: false); @@ -295,7 +301,6 @@ public virtual bool Open() var currentTimestamp = Stopwatch.GetTimestamp(); Dependencies.ConnectionLogger.ConnectionOpened( this, - instanceId, startTimestamp, currentTimestamp, async: false); @@ -306,7 +311,6 @@ public virtual bool Open() Dependencies.ConnectionLogger.ConnectionError( this, e, - instanceId, startTimestamp, currentTimestamp, async: false); @@ -351,10 +355,8 @@ public virtual bool Open() if (_connection.Value.State != ConnectionState.Open) { var startTimestamp = Stopwatch.GetTimestamp(); - var instanceId = Guid.NewGuid(); Dependencies.ConnectionLogger.ConnectionOpening( this, - instanceId, startTimestamp, async: true); @@ -366,7 +368,6 @@ public virtual bool Open() var currentTimestamp = Stopwatch.GetTimestamp(); Dependencies.ConnectionLogger.ConnectionOpened( this, - instanceId, startTimestamp, currentTimestamp, async: true); @@ -377,7 +378,6 @@ public virtual bool Open() Dependencies.ConnectionLogger.ConnectionError( this, e, - instanceId, startTimestamp, currentTimestamp, async: true); @@ -403,7 +403,7 @@ private void CheckForAmbientTransactions() #if NET46 if (Transaction.Current != null) { - Dependencies.TransactionLogger.AmbientTransactionWarning(this); + Dependencies.TransactionLogger.AmbientTransactionWarning(this, Stopwatch.GetTimestamp()); } #elif NETSTANDARD1_3 #else @@ -426,12 +426,7 @@ public virtual bool Close() if (_connection.Value.State != ConnectionState.Closed) { var startTimestamp = Stopwatch.GetTimestamp(); - var instanceId = Guid.NewGuid(); - Dependencies.ConnectionLogger.ConnectionClosing( - this, - instanceId, - startTimestamp, - async: false); + Dependencies.ConnectionLogger.ConnectionClosing(this, startTimestamp); try { @@ -439,12 +434,7 @@ public virtual bool Close() wasClosed = true; var currentTimestamp = Stopwatch.GetTimestamp(); - Dependencies.ConnectionLogger.ConnectionClosed( - this, - instanceId, - startTimestamp, - currentTimestamp, - async: false); + Dependencies.ConnectionLogger.ConnectionClosed(this, startTimestamp, currentTimestamp); } catch (Exception e) { @@ -452,7 +442,6 @@ public virtual bool Close() Dependencies.ConnectionLogger.ConnectionError( this, e, - instanceId, startTimestamp, currentTimestamp, async: false); diff --git a/src/EFCore.Relational/Storage/RelationalDataReader.cs b/src/EFCore.Relational/Storage/RelationalDataReader.cs index c9d5405fd8b..75a6eedfc14 100644 --- a/src/EFCore.Relational/Storage/RelationalDataReader.cs +++ b/src/EFCore.Relational/Storage/RelationalDataReader.cs @@ -26,6 +26,7 @@ public class RelationalDataReader : IDisposable private readonly IRelationalConnection _connection; private readonly DbCommand _command; private readonly DbDataReader _reader; + private readonly Guid _commandId; private readonly IDiagnosticsLogger _logger; private readonly long _startTimestamp; @@ -37,11 +38,13 @@ public class RelationalDataReader : IDisposable /// The connection. /// The command that was executed. /// The underlying reader for the result set. + /// A correlation ID that identifies the instance being used. /// The diagnostic source. public RelationalDataReader( [CanBeNull] IRelationalConnection connection, [NotNull] DbCommand command, [NotNull] DbDataReader reader, + Guid commandId, [NotNull] IDiagnosticsLogger logger) { Check.NotNull(command, nameof(command)); @@ -51,6 +54,7 @@ public RelationalDataReader( _connection = connection; _command = command; _reader = reader; + _commandId = commandId; _logger = logger; _startTimestamp = Stopwatch.GetTimestamp(); } @@ -80,7 +84,9 @@ public virtual void Dispose() _logger.DataReaderDisposing( _connection, + _command, _reader, + _commandId, _reader.RecordsAffected, _startTimestamp, currentTimestamp); diff --git a/src/EFCore.Relational/Storage/RelationalTransaction.cs b/src/EFCore.Relational/Storage/RelationalTransaction.cs index 383fd33e56c..5642437330b 100644 --- a/src/EFCore.Relational/Storage/RelationalTransaction.cs +++ b/src/EFCore.Relational/Storage/RelationalTransaction.cs @@ -61,6 +61,8 @@ public RelationalTransaction( _transactionOwned = transactionOwned; } + public virtual Guid TransactionId { get; } = Guid.NewGuid(); + /// /// Commits all changes made to the database in the current transaction. /// @@ -77,6 +79,7 @@ public virtual void Commit() _logger.TransactionCommitted( _relationalConnection, _dbTransaction, + TransactionId, startTimestamp, currentTimestamp); } @@ -86,7 +89,8 @@ public virtual void Commit() _logger.TransactionError( _relationalConnection, - _dbTransaction, + _dbTransaction, + TransactionId, "Commit", e, startTimestamp, @@ -113,6 +117,7 @@ public virtual void Rollback() _logger.TransactionRolledBack( _relationalConnection, _dbTransaction, + TransactionId, startTimestamp, currentTimestamp); } @@ -123,6 +128,7 @@ public virtual void Rollback() _logger.TransactionError( _relationalConnection, _dbTransaction, + TransactionId, "Rollback", e, startTimestamp, @@ -147,8 +153,10 @@ public virtual void Dispose() _dbTransaction.Dispose(); _logger.TransactionDisposed( - _relationalConnection, - _dbTransaction); + _relationalConnection, + _dbTransaction, + TransactionId, + Stopwatch.GetTimestamp()); } ClearTransaction(); diff --git a/src/EFCore/Storage/IDbContextTransaction.cs b/src/EFCore/Storage/IDbContextTransaction.cs index 430bb756f37..133e71bfd10 100644 --- a/src/EFCore/Storage/IDbContextTransaction.cs +++ b/src/EFCore/Storage/IDbContextTransaction.cs @@ -17,6 +17,11 @@ namespace Microsoft.EntityFrameworkCore.Storage /// public interface IDbContextTransaction : IDisposable { + /// + /// Gets the transaction identifier. + /// + Guid TransactionId { get; } + /// /// Commits all changes made to the database in the current transaction. /// diff --git a/src/EFCore/breakingchanges.netcore.json b/src/EFCore/breakingchanges.netcore.json index 18aedc92da4..93729eff5e4 100644 --- a/src/EFCore/breakingchanges.netcore.json +++ b/src/EFCore/breakingchanges.netcore.json @@ -1,4 +1,9 @@ [ + { + "TypeId": "public interface Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction : System.IDisposable", + "MemberId": "System.Guid get_TransactionId()", + "Kind": "Addition" + }, { "TypeId": "public enum Microsoft.EntityFrameworkCore.Infrastructure.CoreEventId", "Kind": "Removal" diff --git a/src/EFCore/breakingchanges.netframework.json b/src/EFCore/breakingchanges.netframework.json index 18aedc92da4..93729eff5e4 100644 --- a/src/EFCore/breakingchanges.netframework.json +++ b/src/EFCore/breakingchanges.netframework.json @@ -1,4 +1,9 @@ [ + { + "TypeId": "public interface Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction : System.IDisposable", + "MemberId": "System.Guid get_TransactionId()", + "Kind": "Addition" + }, { "TypeId": "public enum Microsoft.EntityFrameworkCore.Infrastructure.CoreEventId", "Kind": "Removal" diff --git a/test/EFCore.Relational.Tests/Storage/RelationalCommandTest.cs b/test/EFCore.Relational.Tests/Storage/RelationalCommandTest.cs index 9a779bea2ab..5982986b633 100644 --- a/test/EFCore.Relational.Tests/Storage/RelationalCommandTest.cs +++ b/test/EFCore.Relational.Tests/Storage/RelationalCommandTest.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Relational.Tests.TestUtilities; @@ -347,48 +348,48 @@ public async Task Can_ExecuteReaderAsync() } public static TheoryData CommandActions - => new TheoryData + => new TheoryData { { new CommandAction( (connection, command, parameterValues) => command.ExecuteNonQuery(connection, parameterValues)), - "ExecuteNonQuery", + DbCommandMethod.ExecuteNonQuery, false }, { new CommandAction( (connection, command, parameterValues) => command.ExecuteScalar(connection, parameterValues)), - "ExecuteScalar", + DbCommandMethod.ExecuteScalar, false }, { new CommandAction( (connection, command, parameterValues) => command.ExecuteReader(connection, parameterValues)), - "ExecuteReader", + DbCommandMethod.ExecuteReader, false }, { new CommandFunc( (connection, command, parameterValues) => command.ExecuteNonQueryAsync(connection, parameterValues)), - "ExecuteNonQuery", + DbCommandMethod.ExecuteNonQuery, true }, { new CommandFunc( (connection, command, parameterValues) => command.ExecuteScalarAsync(connection, parameterValues)), - "ExecuteScalar", + DbCommandMethod.ExecuteScalar, true }, { new CommandFunc( (connection, command, parameterValues) => command.ExecuteReaderAsync(connection, parameterValues)), - "ExecuteReader", + DbCommandMethod.ExecuteReader, true } }; @@ -998,7 +999,7 @@ public async Task Logs_commands_parameter_values( [MemberData(nameof(CommandActions))] public async Task Reports_command_diagnostic( Delegate commandDelegate, - string diagnosticName, + DbCommandMethod diagnosticName, bool async) { var options = CreateOptions(); @@ -1032,8 +1033,8 @@ public async Task Reports_command_diagnostic( Assert.Equal(RelationalEventId.CommandExecuting.Name, diagnostic[0].Item1); Assert.Equal(RelationalEventId.CommandExecuted.Name, diagnostic[1].Item1); - var beforeData = (RelationalDiagnosticSourceBeforeMessage)diagnostic[0].Item2; - var afterData = (RelationalDiagnosticSourceAfterMessage)diagnostic[1].Item2; + var beforeData = (CommandData)diagnostic[0].Item2; + var afterData = (CommandExecutedData)diagnostic[1].Item2; Assert.Equal(fakeConnection.DbConnections[0].DbCommands[0], beforeData.Command); Assert.Equal(fakeConnection.DbConnections[0].DbCommands[0], afterData.Command); @@ -1041,15 +1042,15 @@ public async Task Reports_command_diagnostic( Assert.Equal(diagnosticName, beforeData.ExecuteMethod); Assert.Equal(diagnosticName, afterData.ExecuteMethod); - Assert.Equal(async, beforeData.IsAsync); - Assert.Equal(async, afterData.IsAsync); + Assert.Equal(async, beforeData.Async); + Assert.Equal(async, afterData.Async); } [Theory] [MemberData(nameof(CommandActions))] public async Task Reports_command_diagnostic_on_exception( Delegate commandDelegate, - string diagnosticName, + DbCommandMethod diagnosticName, bool async) { var exception = new InvalidOperationException(); @@ -1101,8 +1102,8 @@ await Assert.ThrowsAsync( Assert.Equal(RelationalEventId.CommandExecuting.Name, diagnostic[0].Item1); Assert.Equal(RelationalEventId.CommandError.Name, diagnostic[1].Item1); - var beforeData = (RelationalDiagnosticSourceBeforeMessage)diagnostic[0].Item2; - var afterData = (RelationalDiagnosticSourceAfterMessage)diagnostic[1].Item2; + var beforeData = (CommandData)diagnostic[0].Item2; + var afterData = (CommandErrorData)diagnostic[1].Item2; Assert.Equal(fakeDbConnection.DbCommands[0], beforeData.Command); Assert.Equal(fakeDbConnection.DbCommands[0], afterData.Command); @@ -1110,8 +1111,8 @@ await Assert.ThrowsAsync( Assert.Equal(diagnosticName, beforeData.ExecuteMethod); Assert.Equal(diagnosticName, afterData.ExecuteMethod); - Assert.Equal(async, beforeData.IsAsync); - Assert.Equal(async, afterData.IsAsync); + Assert.Equal(async, beforeData.Async); + Assert.Equal(async, afterData.Async); Assert.Equal(exception, afterData.Exception); } diff --git a/test/EFCore.Relational.Tests/Storage/RelationalTransactionExtensionsTest.cs b/test/EFCore.Relational.Tests/Storage/RelationalTransactionExtensionsTest.cs index c944dc2dc41..6e895f466f8 100644 --- a/test/EFCore.Relational.Tests/Storage/RelationalTransactionExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Storage/RelationalTransactionExtensionsTest.cs @@ -51,6 +51,8 @@ public void GetDbTransaction_throws_on_non_relational_provider() private class NonRelationalTransaction : IDbContextTransaction { + public virtual Guid TransactionId { get; } = Guid.NewGuid(); + public void Commit() { throw new NotImplementedException(); diff --git a/test/EFCore.SqlServer.FunctionalTests/Utilities/TestRelationalTransaction.cs b/test/EFCore.SqlServer.FunctionalTests/Utilities/TestRelationalTransaction.cs index 8b7683d57c1..965ed366219 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Utilities/TestRelationalTransaction.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Utilities/TestRelationalTransaction.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Data.Common; using System.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -30,6 +31,8 @@ public TestRelationalTransaction( { } + public virtual Guid TransactionId { get; } = Guid.NewGuid(); + public TestRelationalTransaction(TestSqlServerConnection connection, IDbContextTransaction transaction) { _testConnection = connection; diff --git a/test/EFCore.Tests/TestUtilities/TestInMemoryTransactionManager.cs b/test/EFCore.Tests/TestUtilities/TestInMemoryTransactionManager.cs index ddef53cf9f9..069cba44a50 100644 --- a/test/EFCore.Tests/TestUtilities/TestInMemoryTransactionManager.cs +++ b/test/EFCore.Tests/TestUtilities/TestInMemoryTransactionManager.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -46,6 +47,8 @@ public TestInMemoryTransaction(TestInMemoryTransactionManager transactionManager TransactionManager = transactionManager; } + public virtual Guid TransactionId { get; } = Guid.NewGuid(); + private TestInMemoryTransactionManager TransactionManager { get; } public void Dispose()