Skip to content

Commit

Permalink
Implement entity materialization interception (#28274)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers authored Jun 20, 2022
1 parent e09ad8b commit 5ff4696
Show file tree
Hide file tree
Showing 35 changed files with 1,793 additions and 235 deletions.
4 changes: 2 additions & 2 deletions src/EFCore.Relational/Diagnostics/IDbCommandInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,8 @@ Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, Canc
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down
20 changes: 10 additions & 10 deletions src/EFCore.Relational/Diagnostics/IDbConnectionInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ DbConnection ConnectionCreated(ConnectionCreatedEventData eventData, DbConnectio
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand All @@ -103,8 +103,8 @@ InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventDat
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -149,8 +149,8 @@ Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData event
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand All @@ -170,8 +170,8 @@ InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventDat
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -230,8 +230,8 @@ InterceptionResult ConnectionDisposing(DbConnection connection, ConnectionEventD
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down
40 changes: 20 additions & 20 deletions src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ ValueTask<DbTransaction> TransactionUsedAsync(
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -217,8 +217,8 @@ void TransactionCommitted(DbTransaction transaction, TransactionEndEventData eve
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -257,8 +257,8 @@ Task TransactionCommittedAsync(
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -289,8 +289,8 @@ void TransactionRolledBack(DbTransaction transaction, TransactionEndEventData ev
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -329,8 +329,8 @@ Task TransactionRolledBackAsync(
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -360,8 +360,8 @@ void CreatedSavepoint(DbTransaction transaction, TransactionEventData eventData)
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -400,8 +400,8 @@ Task CreatedSavepointAsync(
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -434,8 +434,8 @@ void RolledBackToSavepoint(DbTransaction transaction, TransactionEventData event
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -474,8 +474,8 @@ Task RolledBackToSavepointAsync(
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down Expand Up @@ -505,8 +505,8 @@ void ReleasedSavepoint(DbTransaction transaction, TransactionEventData eventData
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is false, the EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is true, then EF will suppress the operation
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will suppress the operation
/// it was about to perform.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// the operation is to return the <paramref name="result" /> value passed in.
Expand Down
88 changes: 88 additions & 0 deletions src/EFCore/Diagnostics/IMaterializationInterceptor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.EntityFrameworkCore.Diagnostics;

/// <summary>
/// A <see cref="ISingletonInterceptor" /> used to intercept the various parts of object creation and initialization when
/// Entity Framework is creating an object, typically from data returned by a query.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-interceptors">EF Core interceptors</see> for more information and examples.
/// </remarks>
public interface IMaterializationInterceptor : ISingletonInterceptor
{
/// <summary>
/// Called immediately before EF is going to create an instance of an entity. That is, before the constructor has been called.
/// </summary>
/// <param name="materializationData">Contextual information about the materialization happening.</param>
/// <param name="result">
/// Represents the current result if one exists.
/// This value will have <see cref="InterceptionResult{Object}.HasResult" /> set to <see langword="true" /> if some previous
/// interceptor suppressed execution by calling <see cref="InterceptionResult{Object}.SuppressWithResult" />.
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult{Object}.HasResult" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult{Object}.HasResult" /> is <see langword="true" />, then EF will suppress creation of
/// the entity instance and use <see cref="InterceptionResult{Object}.Result" /> instead.
/// An implementation of this method for any interceptor that is not attempting to change the result
/// should return the <paramref name="result" /> value passed in.
/// </returns>
InterceptionResult<object> CreatingInstance(MaterializationInterceptionData materializationData, InterceptionResult<object> result)
=> result;

/// <summary>
/// Called immediately after EF has created an instance of an entity. That is, after the constructor has been called, but before
/// any properties values not set by the constructor have been set.
/// </summary>
/// <param name="materializationData">Contextual information about the materialization happening.</param>
/// <param name="instance">
/// The entity instance that has been created.
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// The entity instance that EF will use.
/// An implementation of this method for any interceptor that is not attempting to change the instance used
/// must return the <paramref name="instance" /> value passed in.
/// </returns>
object CreatedInstance(MaterializationInterceptionData materializationData, object instance)
=> instance;

/// <summary>
/// Called immediately before EF is going to set property values of an entity that has just been created. Note that property values
/// set by the constructor will already have been set.
/// </summary>
/// <param name="materializationData">Contextual information about the materialization happening.</param>
/// <param name="instance">The entity instance for which property values will be set.</param>
/// <param name="result">
/// Represents the current result if one exists.
/// This value will have <see cref="InterceptionResult.IsSuppressed" /> set to <see langword="true" /> if some previous
/// interceptor suppressed execution by calling <see cref="InterceptionResult.Suppress" />.
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="false" />, then EF will continue as normal.
/// If <see cref="InterceptionResult.IsSuppressed" /> is <see langword="true" />, then EF will not set any property values.
/// An implementation of this method for any interceptor that is not attempting to suppress
/// setting property values must return the <paramref name="result" /> value passed in.
/// </returns>
InterceptionResult InitializingInstance(MaterializationInterceptionData materializationData, object instance, InterceptionResult result)
=> result;

/// <summary>
/// Called immediately after EF has set property values of an entity that has just been created.
/// </summary>
/// <param name="materializationData">Contextual information about the materialization happening.</param>
/// <param name="instance">
/// The entity instance that has been created.
/// This value is typically used as the return value for the implementation of this method.
/// </param>
/// <returns>
/// The entity instance that EF will use.
/// An implementation of this method for any interceptor that is not attempting to change the instance used
/// must return the <paramref name="instance" /> value passed in.
/// </returns>
object InitializedInstance(MaterializationInterceptionData materializationData, object instance)
=> instance;
}
Loading

0 comments on commit 5ff4696

Please sign in to comment.