dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.48k stars 3.13k forks source link

Events and interception (aka lifecycle hooks) #626

Open divega opened 9 years ago

divega commented 9 years ago

Done in 2.1

Done in 3.1

Done in 5.0

Done in 6.0

Done in 7.0

Backlog

Note: below is a copy of a very old EF specification and reflects thinking from several years ago. A lot of things aren't valid anymore.

We define EF Core lifecycle hooks as the general feature that enables an application or library to sign up to be invoked or notified whenever certain interesting conditions or actions occur as part of the lifecycle of entities, properties, associations, queries, context instances, and other elements in the Entity Framework stack.

For example:

  1. An application can provide a method that will be invoked automatically whenever an object is about to be saved, or it can subscribe to an event that fires when an object is created and its properties initialized, etc.
  2. A framework extension can register an interceptor that gives it an opportunity to rewrite query expression trees before they get translated by EF. This could be used to validate whether a user has access to specific information or to filter query results based on per DbContext filter (see #6440).
  3. Execute SQL after a DbConnection is opened (to use features such as SQL Server App Role)

The need for lifecycle hooks

We want to enable customers to write business logic that triggers in the different stages of the lifecycle of these objects, following well factored coding patterns. We also want framework writers to be able to use these hooks to extend EF Core in useful ways.

In previous versions of Entity Framework we already exposed a few lifecycle hooks. For instance, we had the AssociationChanged and ObjectStateManagerChanged events since the first version, and the ObjectMaterialized event was added in EF4. Up until EF6.x many of the existing hooks are not exposed in the DbContext API. In EF6 we also added several low level extensibility points in Interception that can be used too as lifecycle hooks.

There is a continuum of capabilities related and overlapping with lifecycle hooks, e.g.:

Name Pri Location Cancel or override Description & sample scenario
QueryExecuting 0 DbContext Yes Query interception, custom query caching.
QueryExecuted 3 DbContext No When Execute happened, before the reader is read. Tracing?
QueryCompleted 3 DbContext No After DbDataReader is closed. Tracing?
EntityStateChanged 0 DbContext No Signals all state changes
EntityStateChanging 3 DbContext ? Undo changes or change proposed values before they are set?
ConnectionProvisioning 2 DbContext Yes Execute additional code to make sure the connection is alive, or do logging
ConnectionReleasing 2 DbContext Yes Cleanup something done during Ensure / StartUsingConnection
ConnectionOpened 2   No More likely for tracing. Since SqlClient has fixed invalid connection pools, then this is lower priority
ConnectionOpening 1 DbContext Yes Slightly simpler to use than Ensure/Start, would not require user to check current state. Could also be used for tracing.
ConnectionClosed 1   No  
ConnectionClosing 1 DbContext Yes Slightly simpler to use than Release/Stop, would not require user to check the initial state. Could also be used for tracing.
OnModelCreating 0 DbContext Yes Tweak model before it is cached.
OnModelCreated 1 DbContext Yes Signal that the model is done and execute some custom code, possibly related to caching logic. . Issue: do we need this for ObjectContext? Issue: if the user is going to implement his own caching, we should have an abstract class or interface for that.
ModelCacheLookup 2 DbContext Yes Implement your own caching logic. Tracing?
ModelCacheHit 2 DbContext Yes Execute additional code when the model is found in the cache. Tracing?
EntityLoading 1 DbContext, DbEntityEntry No After object instance is created but before its properties are initialized. Can be used to reset a flag that will be set in newly created instances but shouldn’t be set during initialization, i.e. for validation.
EntityLoaded 0 DbContext, DbEntityEntry No Can be used to setup anything after an object has been materialized, i.e. event handlers, flags, etc.
CollectionLoading 1 DbContext, DbEntityEntry DbCollectiohnEntry No Can be used to setup anything on a collection after it is created but before it is populated. Issue: Could be used to provide your own collection?
CollectionLoading 1 Context, Entity or Collection No Can be used to setup anything on a collection after it has been created and populated, i.e. listeners for its changed event.
ObjectTypeResolving 1 Context Yes Could be used to specify a different type than the original one, i.e. to implement your own proxy mechanism. It should be per type but could return a Func<T> that returns a new instance and the result could be compiled into materialization delegates.
CollectionTypeResolving 1 Context Yes Something similar to ObjectTypeResolving but for collections. Could be used to replace the default collection type with a custom proxy collection with additional functionality (i.e. paging, fine grained lazy load).
Virtual OnSavingChanges Medium DbContext No Can be used to re-implement SaveChanges but still invoke the existing SavingChanges event
SavedChanges Low Context No Could be used to execute cleanup code after SaveChanges. For instance, to call AcceptChanges on each STE change tracker. It is lower priority because virtual SaveChanges covers most scenarios.
EntityStateChanging Low Context, Entity Yes For an entity instance or type in particular we could avoid putting in the modified state. So even if the properties are read-write, the context ignores changes to this entity. Could be also used to suspend fixup on an entity that is being detached.
EntityStateChanged High Context, Entity No Executes logic after an entity has been put in a certain state. Can be used to setup property values, restore state after the changing event.
PropertyChanging Low Context, Entity Yes Any time a property is about to be changed by the framework or any party, if notification or interception is enabled by the entity type. Should make original and new value available. Should also work for navigation, scalar and complex types properties. Tracing?
PropertyChanged High Context, Entity No Any time a change in a property value change is detected.
PropertyLoading High Context, Entity, Collection Yes Intercepts, overrides de loading of a property. Could be used to support loading of properties using stored procedures.
PropertyLoaded Medium Context, Entity, Collection No Tracing?
Writetable IsLoaded High Context, Entity Yes Allows cancelling the loading of a property.
CollectionChanging Medium Context Yes Any time a collection is about to be changed by the framework or any party, if interception is enabled
CollectionChanged Medium Context, Entity No Any time a change to a collection has been detected.
AssociationChanging Low Context, RelatedEnd Yes Can be used to prevent an association from being changed, or to execute business logic when the association is about to change.
AssociationChanged Medium Context, RelatedEnd No Can be used to execute additional logic after an association is changed, i.e. user can explicitly cascade relationships removals into dependent removals, workaround current databinding shortcomings.
RowValidate , RowValidateAdded, RowValidateModified, RowValidateDeleted Medium Context Yes Storage level version of ObjectValidate. Tracing?
SavingChanges event 0 DbContext ? Currently only available on ObjectContext. Should make trigger OnSavingChanges method protected.

Existing hooks

Name Description & sample scenario
virtual Dispose This can be used to do additional cleanup, i.e. on entity instances.
virtual SaveChanges Can be used to execute additional logic before, after or instead of saving changes.

Some open issues:

  1. Need to prototype some coding patterns and try them.
  2. Is logging and tracing part of this API? It seems that ideally we should have the same level of flexibility for hooking mechanisms with logging and tracing as we end up having with this API.
  3. Second level cache should probably expose its hooks through the same mechanisms.
  4. Should we provide low level query interception points with the same mechanisms, i.e. as command tress and store commands? Should we do the same for CUD store commands? Would need to make sure those work well with caching.
  5. Can we get some level of support for async execution of queries with this hook?
  6. Should we provide enough lifecycle hooks to implement custom fixup logic?
  7. Areas of overlap with other extensibilities: read and write properties in object mapping, proxy type creation (can be imperative vs. event driven), equality and snapshot comparisons for change tracking extensibility.
  8. What about customizing identity resolution?
  9. Is Logging and Tracing part of the lifecycle hooks
  10. Is Query interception part of the lifecycle hooks
  11. Even without query interception we should expose when we are about to execute (imagine a profiling tool that measures how much query compilation costs).
  12. Is ContinueOnConflict part of the lifecycle hooks
  13. How do we improve diagnostics? Can we have OnError
  14. Need to do prioritization, costing and scoping
  15. Should we have a fine grained version of CollectionAdding / CollectionRemoving with support for magic methods on the entities to enable collection patterns? We would need a pattern for Contains checks also.
  16. There is a conversation about splitting AssociationChanged this event into properties and collection changes. However, there should be a way to tell the difference between a scalar property change and a nav prop. Should we make AssociationChanged more accessible and add AssociationChanging? This would provide a way to intercept changes in associations independently of cardinality, constraints, etc.
  17. AssociationChanging would need the entity and collection types to collaborate to avoid changes from being made to the graph.
natemcmaster commented 8 years ago

I started prototyping some ideas as a part of my investigation of setting SQLite pragma options when a connection opens. It seems this feature would be generally useful in solving several other feature requests. Can we considering moving this off backlog?

rowanmiller commented 8 years ago

I think we need @divega in the office to design this one, the all up feature is pretty large and wide-reaching. We also have some higher priority things to work on first. If you are specifically looking at connection pre-amble then I think we can treat that as a smaller feature that we work on now.

janhartmann commented 7 years ago

Will this make it into the next release?

Antaris commented 7 years ago

@rowanmiller In terms of an EF Core ObjectMaterialized style hook, can you give me some pointers as to where I can tackle this as of now?

divega commented 7 years ago

Permission validation and filtering are other scenarios that could be attained with lifecycle hooks (see #6440).

dazinator commented 7 years ago

Will this also take care of the following scenario?

I'd like to add an entity to a DbContext (to be inserted or updated etc), but also subscribe to be notified once the entity has been saved, so i can handle taking its newly updated values (i.e the database generated values that get poplated after a SaveChanges() - like it's ID etc) and do something with them.


                var dbContext = GetExistingDbContextInstance();           
                var newItem = new SomeEntity();
                dbContext.SomeEntities.Add(newItem);
               // I am quite far down in an object graph, and SaveChanges() will eventually be called
               // later on by something higher up, co-ordinating this transaction. I'd like to be notified
              // here though once SaveChanges() has been called and this entity has been persisted, so I can grab the
              // the updated entity values.
              //   dbContext.OnceSaved(newItem, ()=>{   // ooh someEntity.Id is now populated! })  

Something along the lines of:

 dbContext.OnceSaved(someEntity, ()=>{   // ooh someEntity.Id is now populated! })

Where the callback would be invoked after dbContext.SaveChanges() is called.

Antaris commented 7 years ago

@dazinator I'm currently working on an extension project for EFCore (https://github.com/Antaris/EntityFrameworkCoreExtensions) which will allow you to do what you want, eventually.

I have a number of working hooks including change tracking, value materialization, querying and storage. It's still a WIP though.

SidShetye commented 7 years ago

@rowanmiller What's the expected release date on this? It's been open for almost 2-1/2 years

rowanmiller commented 7 years ago

@sidshetye it's planned to be in our 2.0 release (at least the first set of hooks). No specific dates on that yet, but it's the release we are starting work on now.

tpanthier commented 7 years ago

In the mean time, using EF Core 1.1, what would be the recommended method for executing a SQL statement straight after a DbConnection is opened?

We are using RLS for implementing multitenancy and I'd like to know if there's any method for setting the TenantId until EF Core 2.0 is released.

ajcvickers commented 7 years ago

@tpanthier You could try registering for an event on the DbConnection itself.

ajcvickers commented 7 years ago

Punting this because we are out of time. /cc @divega

michaelaird commented 7 years ago

With this issue being open for 2.5 years and the various other issues that have been closed due to referencing this issue, I've lost track of whether two specific scenarios we care about are covered by other cases and are or are not supported in 2.0.

  1. As part of our multi-tenancy solution, we currently subscribe to DbContext.Database.Connection.StateChange. Whenever the state changes to Open, we issue a SQL command to set the the current tenant id in session_context.

  2. In EF 6, dates loaded from the DB have a kind of Unspecified. In order to coerce these into UTC, we're hooking into ((IObjectContextAdapter)DbContext).ObjectContext.ObjectMaterialized and calling DateTime.SpecifyKind for specific fields that we care about being in UTC.

Can you confirm if either or both of these scenarios will be possible with EFCore 2.0?

ajcvickers commented 7 years ago

@michaelaird Unfortunately, there is no change on either of those issues for 2.0. There is a high chance that they will make it in for 2.1.

michaelaird commented 7 years ago

Got it. Thanks for the update.

Off-topic but slightly related: My observation of the 2.0 milestone across all the .net core projects is that it represents a solid "step up" in stability and general breadth of feature support. With that stability in mind, it would be great if there were more frequent pre-release packages available between 2.0 and 2.1. In particular it would help us get to try these features that just barely didn't make the 2.0 release....

ajcvickers commented 7 years ago

@michaelaird I hear you. On the EF team we don't really control when the releases happen or how many pre-releases there are, but we do push for them to be frequent as much as we can.

SidShetye commented 7 years ago

Guys - do you genuinely think it's acceptable performance when you've had 2.5 years to track, plan and execute - and yet it consistently misses releases? This is open since Sept of 2014. Very disappointing. Especially knowing you guys are clever :(

michaelaird commented 7 years ago

hey @sidshetye , I don't know if you ship commercial software for a living, but I do. And I aim to get things into releases all the time that get re-prioritized by the business and other things that are more important get pulled in ahead. It drives me crazy, as I'm sure it does to the EF team, when I don't have enough hours in the day to deliver all the features that I know my users want.

Let's support the EF team in what they are delivering and not beat them up too much for what is missing the cut.

dazinator commented 7 years ago

@michaelaird I agree, however negative feedback is as important as positive feedback and both kinds are better than no feedback at all. If you aren't getting any feedback it usually means no one cares! What you are witnessing is someone who cares enough about EF to express their dissapointment over an issue and I think it's perfectly valid and even useful for the EF team to hear that. Any attempt to silence such a thing would not be constructive imho. I am also certain that the EF team, being highly professional, are perfectly capable of handling both positive and negative feedback on issues without needing any one of us to jump in for them.

SidShetye commented 7 years ago

@michaelaird Yes, I ship commercially. Including security and voice for 60% of all mobile phones - globally. Code that defined "carrier grade". But making this about me is a distraction - the observation stands even if I personally never shipped a single line of code.

Since we're quickly off topic now, I'll get back with the following suggestions to the EF team:

  1. If I've offended anyone on the EF team, please accept my apologies since the goal was never to upset anyone but to draw attention that this is a serious for some folks. Without this, EF 7 isn't a shipping product. And .NET core isn't a production option (for us and customers). Because ... dependencies.
  2. Please, please spend more time on customer communications. While intricate foreign policies and constitutional debates can be done via 140 characters, customer communications (unfortunately) needs more.
  3. For this specific issue, given the delays - could you at least share the final expected interface/design? I understand ironing out the underlying implementation may take more time. Could be a simple mapping of EF6 hooks (e.g. ObjectContext.ObjectMaterialized and ObjectContext.ObjectContext) to their equivalent EF7 hooks + newer hooks.

I hope my/anyone's feedback doesn't distract from the teams achievements. At the end of the day, we're all trying to make the world a better place through better software. Just don't keep us waiting ;) !

Thanks, Sid


This turned out longer than I expected, so I'll get back to work. Cheers.

ilya-chumakov commented 7 years ago

As we don't have hooks yet, I would like to ask about DbContext.Database.Connection.StateChange event. Is it safe to subscribe on it without un-subscribe? What is DbConnection CLR object lifetime if EFCore is used in ASP.NET app? As I see, IRelationalConnection is registered as Scoped in DI, and DbConnection's lifetime is the same. I could assume if the subscriber also is registered as Scoped, we could relax and don't worry about memory leaking... or not?

@michaelaird, @ajcvickers could you help?

ajcvickers commented 7 years ago

@ilya-chumakov When EF creates the DbConnection for you, then it's lifetime is the same as the DbContext--it will be disposed when the DbContext is disposed. You can also create your own DbConnection and pass it to UseSqlServer (or equivalent) in which case you can make the lifetime longer.

So, if your subscriber has the same lifetime as your DbContext and EF is creating the DbConnection, then the subscriber, context, and connection should all have the same lifetime.

sjb-sjb commented 6 years ago

@rowanmiller commented that some hooks are coming in 2.0, and in https://github.com/aspnet/EntityFramework/wiki/Roadmap there is a one-sentence description, but I haven't been able to find anything else on it. Is there more documentation or pointers out there?

I am interested in hooks for entity state transition. To this end I am using the following approach:

        var localViewListener = dbContext.GetService<Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ILocalViewListener>();
        localViewListener.RegisterView(StateManagerChangedHandler);

However the callback for entity state transition does not provide all the information one might desire. Specifically, for example, if a transition from Modified to Unmodified occurs then we do not know whether this is due to AcceptAllChanges or due to some form of Reject Changes, or possibly due to some other reason. For that, you need to add a flag in your calling code. You need this information to know, for example, in your entity view model whether the current value has changed or the original value has changed. So when you get around to the hooks for entity state transitions, I would ask that you include some indication of whether AcceptAllChanges is in progress or RejectAllChanges is in progress (and I'm hoping you will add RejectAllChanges !)

divega commented 6 years ago

@sjb-sjb if you look in the roadmap you will see that lifecycle-hooks is in the list of "Features originally considered but for which we have made no progress and are essentially postponed".

I will let @ajcvickers comment on whether there is any reasonable way to workaround current limitations and get notified of those changes by using internal APIs but without having to wrap the whole set of change tracking services, but that seems unlikely.

ajcvickers commented 6 years ago

I can't think of a workaround off the top of my head.

kdcarlisle42 commented 6 years ago

Are there any, or going to be any, workaround/solutions for DbInterception? Based on this thread and the roadmap it seems that it's not going to be available for awhile. We are starting some new projects and want to use .Net Core / EF Core, but I'm not sure how to translate our existing DbInterception process.

We are using interception to inspect the sql query and replace [SECURITY_VIEW] with an actual view name. In our current system, each user has their own security view. Views could be added/removed each day, so we cannot create a static context.

In our latest code, which uses EF6, we tested dynamically compiling the model vs interception. Once we started load testing, we found interception to be the winner.

We could go back to writing sql stored procedures, but I'd prefer not to.

Any thoughts/ideas would be greatly appreciated.

ajcvickers commented 6 years ago

@kdcarlisle42 You could investigate using the DiagnosticSource events documented in https://github.com/aspnet/EntityFramework/blob/dev/src/EFCore.Relational/Diagnostics/RelationalEventId.cs

These events give you access to the DbCommand, etc, before it is executed, and it may be possible for code to manipulate these objects to do what you need. However, it's not as flexible as DbInterception in EF6. I would be interested in hearing about your experience if you go this route.

(Note that these events have changed significantly between 1.1 and 2.0, so if you write something for 1.1, then it will need to be modified to work with 2.0.)

sjb-sjb commented 6 years ago

I don't know what the limitations are that were referred to by @divega and @ajcvickers. Could one not simply add an event like this to DbContext?

    public event TypedEventHandler<IEntityStateWatcher, EntityStateTransitionEventArgs> EntityStateTransition;

    public DbContext( ... )
    {
        ...
        var localViewListener = this.GetService<Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ILocalViewListener>();
        localViewListener.RegisterView(StateManagerChangedHandler);
        ...
    }

    private void StateManagerChangedHandler(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry entry, EntityState previousState)
    {
        var entityEntry = entry.ToEntityEntry();
        this.EntityStateTransition?.Invoke(this, new EntityStateTransitionEventArgs(entityEntry, previousState));
    }
olman21 commented 6 years ago

I've been following this issue for a couple of months, I need to perform a soft-delete feature in my Application, I know how to "override" actual deletes with "update the delete flag" but not a clue how to filter the "soft-deleted" records once a query is performed, this would be easy with hooks, but in this case I can't imagine how to workaround this.

ajcvickers commented 6 years ago

@olman21 Take a look at Global Query Filters: https://blogs.msdn.microsoft.com/dotnet/2017/05/12/announcing-ef-core-2-0-preview-1/

ajcvickers commented 6 years ago

Consider what can be done to observe transactions commit/rollback--see #9429

KallDrexx commented 6 years ago

Can this task (if it ever gets prioritized) support passing some sort of timings in with the hooks?

Right now our Asp.net core with EF core running on Azure is having periods of non-reproducible high 75, 90, 95, and 99 percentile response times. We want to hook into DB operations so when our special request logging is returned it returns the # of queries and average db request/response time for each so we can see if this inconsistency is db related or not.

Right now it seems possible to do this for SaveAsync and FindAsync calls on the DbContext by overriding those calls and putting a stopwatch around them, but I don't see an easy way to get the timings of any Linq based queries, without manually adding code around every single EF core code block.

SidShetye commented 6 years ago

Still looking for ObjectMaterialized and SavingChanges equivalent hooks. With the passage of time (and .NET standard 2.0 out), do we have a cleared release date? Pretty please?

divega commented 6 years ago

@sidshetye In case you haven't noticed this issue has been recently assigned to the 2.1 release as a "stretch priority". The exact hooks we will prioritize hasn't been decided yet, but your input will be considered.

divega commented 6 years ago

@KallDrexx it sounds like you should be able to use the logging & diagnostics functionality in EF Core for this. Have you had a chance to try that?

cc @ajcvickers

KallDrexx commented 6 years ago

@divega Maybe I am missing something but I can't find any documentation that shows how this can be effectively used, at least for my use case.

The first issue is I don't see much in the logging facilities that would allow me to output query times (including network times) so I am not totally sure how to grab that.

The second issue is that in production we whitelist what logs are produced to keep costs down and to keep logs concise and easy to search through (i.e. one log record per request with all relevant data in a json record). This makes it extremely easy to utilize tools such as Elastic Search to find complete details about a total request instead of making hard assumptions and having to coalesce 20 different log entries to get a complete view of a single request.

From what I can currently see, utilizing the current logging infrastructure means creating a custom ILogger with a lot of non-trivial hoop jumping to get query data to flow out of our custom Logger into the request context, so at the end of the request the data can be coalesced into our simple request.

divega commented 6 years ago

@KallDrexx if logging doesn't meet your requirements, EF Core also publishes diagnostics events using DiagnosticSource.

There is some information about how to consume this information programmatically at https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md#consuming-data-with-diagnosticlistener. It also possible to consume this diagnostics events through ETW on Windows.

KallDrexx commented 6 years ago

Thank you very much, I had not known that there was a diagnostic system built into .net core, so I will investigate that route. Really appreciate the response.

On Mon, Aug 28, 2017 at 1:31 PM, Diego Vega notifications@github.com wrote:

@KallDrexx https://github.com/kalldrexx if logging doesn't meet your requirements, EF Core also publishes diagnostics events using DiagnosticSource.

There is some information about how to consume this information programmatically at https://github.com/dotnet/ corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/ DiagnosticSourceUsersGuide.md#consuming-data-with-diagnosticlistener. It also possible to consume this diagnostics events through ETW https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md#consuming-diagnosticsource-data-with-eventlisteners-and-etw on Windows.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/aspnet/EntityFrameworkCore/issues/626#issuecomment-325420694, or mute the thread https://github.com/notifications/unsubscribe-auth/AAIggYAUt_9e-jdhU8-9EajopCLRy0nWks5scvlugaJpZM4Cesel .

SidShetye commented 6 years ago

@divega thanks for the update, missed that tag update. Though it's not very comforting that this is as low of a priority as 'stretch' / "if we have bonus time left".

To us this is a deal breaker for EF core (and therefore .NET core). Hope .NET core and EF core get more investments. It ultimately boosts Azure deployments - at least for us.

mguinness commented 6 years ago

@sidshetye Although not ideal, a couple of possible workarounds for your needs are a custom Entity Materializer Source and another library EntityFramework.Triggers.

AndriySvyryd commented 6 years ago

@ajcvickers Add hooks for customizing a model and the model cache key using with a context instance

codetuner commented 6 years ago

For a concrete application of SavingChanged and ObjectMaterialized in EF6, see my article about hybrid storage on CodeProject. Inspired by the Core way of doing things, I defined an extension method "UseHybridStorage()" to DbContext that registers to the ObjectMaterialized and SavingChanges events. Hence no subclassing is needed. It would also be very usefull to have access to the Context from within those lifecycle hooks.

Would what I did in the article be possible with EF Core 2.1 too ? (See the OnObjectMaterialized and OnSavingChanges methods just above the "Entity State Handling Issue" paragraph.)

jaredcnance commented 6 years ago

I think it would also be beneficial to have some form of hook to notify if a LINQ expression was not able to be translated. I am aware that this gets logged, but it would be helpful to have a programmatic way to escalate it from a simple WARN log to some other form of notification. This, of course, makes the most sense during development but it is not always obvious to the developers.

The primary situation I'm thinking of is one where a library (for json:api or graphql as examples) sits on top of entity framework and is responsible for interacting with EF. This would enable the library to surface these kinds of problems in a more obvious way to the developers and provide framework-specific solutions.

ajcvickers commented 6 years ago

@janhartmann It is already possible to:

public class MyListener : IObserver<DiagnosticListener>, IObserver<KeyValuePair<string, object>>
{
    public void OnCompleted()
    {
    }

    public void OnError(Exception error)
    {
    }

    public void OnNext(DiagnosticListener listener)
    {
        if (listener.Name == DbLoggerCategory.Name)
        {
            listener.Subscribe(this);
        }
    }

    public void OnNext(KeyValuePair<string, object> value)
    {
        if (value.Key == RelationalEventId.QueryClientEvaluationWarning.Name)
        {
            var payload = (QueryModelClientEvalEventData)value.Value;
            Console.WriteLine("Client eval happening: " + payload);
        }
    }
}

Then somewhere in app startup:

DiagnosticListener.AllListeners.Subscribe(new MyListener());
ErikEJ commented 6 years ago

This would be nice to have in docs

ajcvickers commented 6 years ago

Thanks Erik. Filed https://github.com/aspnet/EntityFramework.Docs/issues/583

SidShetye commented 6 years ago

@ajcvickers @divega : is there a firm release date we can go by? I have multiple customers asking us to expand Crypteron to support EF Core. We've been deferring them to EF6 for years now but I'm wondering if 2017 will be special

sjb-sjb commented 6 years ago

I would like to renew my vote for state transitions to become part of the public API (see Jul 13 above).

ajcvickers commented 6 years ago

@sidshetye Unfortunately we don't have any dates that we can share yet.

SidShetye commented 6 years ago

@ajcvickers That's disappointing. It makes roadmap planning impossible for your customers (us and in-turn our customers). We certainly appreciate the work by the team and I know it's comforting to not state a release date (that you're now held accountable to!). But may I challenge the team to step outside that comfort zone? There has got to be some plan and some target date ... doesn't help to keep the community in the dark.

Again, love the work - just wish there was more transparency to facilitate business.