Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lifecycle hooks #626

Open
divega opened this issue Sep 4, 2014 · 130 comments

Comments

@divega
Copy link
Member

commented Sep 4, 2014

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)

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.:

  • We want to improve everyone’s ability to diagnose functional and performance issues with their code using Entity Framework by recording information about interesting events and conditions in the EF stack, but that is essentially logging (tracked in #218 and other work items). By comparison, lifecycle hooks allows to modify the outcome of these events.
  • Also the DI-based architecture of EF Core allows for a very granular capability to wrap and replace individual implementation services, which can potentially be used to extend EF and to execute business logic. By comparison, lifecycle hooks is about adding simple and first class hooks that can easily be used to react to interesting conditions without having to re-implement the complete interface of a service.
@natemcmaster

This comment has been minimized.

Copy link
Member

commented Jun 21, 2016

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

This comment has been minimized.

Copy link
Member

commented Jun 21, 2016

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

This comment has been minimized.

Copy link

commented Sep 3, 2016

Will this make it into the next release?

@Antaris

This comment has been minimized.

Copy link

commented Sep 30, 2016

@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

This comment has been minimized.

Copy link
Member Author

commented Oct 13, 2016

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

@dazinator

This comment has been minimized.

Copy link

commented Nov 29, 2016

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

This comment has been minimized.

Copy link

commented Nov 29, 2016

@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

This comment has been minimized.

Copy link

commented Jan 4, 2017

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

@smitpatel

This comment has been minimized.

Copy link
Contributor

commented Dec 13, 2018

@WillSullivan - If you want to do before any kind of query execution starts, then override IQueryCompiler.
If you want to change only when query is being compiled then override IDatabase.CompileQuery* methods.

@weitzhandler

This comment has been minimized.

Copy link
Contributor

commented Dec 24, 2018

I need to run certain operations on the database when it got created. Is there a way to get a notification when it's creation completed (i.e. after calling EnsureCreated created the DB)?

@ErikEJ

This comment has been minimized.

Copy link
Contributor

commented Dec 24, 2018

Is this for testing? EnsureCreated should not be used in production.

@weitzhandler

This comment has been minimized.

Copy link
Contributor

commented Dec 24, 2018

Thanks for your notice @ErikEJ, my question is also about context.Database.Migrate(). Is there a way to intercept those calls and perform stuff afterwards?

@smitpatel

This comment has been minimized.

Copy link
Contributor

commented Dec 26, 2018

@weitzhandler - How about writing custom SQL in migration files? After database is created, the first line executed on server would be first line in up method of very first migration file

@weitzhandler

This comment has been minimized.

Copy link
Contributor

commented Dec 27, 2018

@smitpatel @ErikEJ
I've opened a new issue.

@SidShetye

This comment has been minimized.

Copy link

commented Jan 16, 2019

Hi folks - any news on when this will make the release? Been requested since 2014, now 2019.
2019 - 2014 = 5 :(

@Igneous01

This comment has been minimized.

Copy link

commented Feb 8, 2019

It's sad that EF still doesn't support this when Hibernate has had this capability for many years now.

If I want to add basic auditing and Guid generation I have to hand roll it myself each time.

This should be something that's possible within EF.

`
public class Audit {

@Column(name = "created_on")
private LocalDateTime createdOn;

@Column(name = "created_by")
private String createdBy;
 
@Column(name = "updated_on")
private LocalDateTime updatedOn;

@Column(name = "updated_by")
private String updatedBy;

@PrePersist
public void prePersist() {
    createdOn = LocalDateTime.now();
    createdBy = LoggedUser.get();
}

@PreUpdate
public void preUpdate() {
    updatedOn = LocalDateTime.now();
    updatedBy = LoggedUser.get();
}

//Getters and setters omitted for brevity

}
`

@mguinness

This comment has been minimized.

Copy link

commented Feb 8, 2019

@Igneous01 You can already achieve this in EF Core - see Generate tracking columns for more details.

@jakenuts

This comment has been minimized.

Copy link

commented Feb 14, 2019

SaveChanges seems like a great place to be able to intercept/extend a context (auditing, caching events) and now with DbContextPooling overriding those methods to call services is less manageable as they can't be passed in to the constructor. A BeforeSaveChanges(Async), AfterSaveChanges(Async) and ErrorSavingChanges(Async) event would be awesome.

@ajcvickers

This comment has been minimized.

Copy link
Member

commented Feb 14, 2019

@jakenuts A couple of points:

  • If pooling is limiting what you need to do, try switching pooling off. In most scenarios the performance gain is negligible.
  • I'm not sure these events would help that much over SaveChanges in this respect, since you still need to register the events, and if there is a convenient place to do that, then why not just set context state there instead.
@sjb-sjb

This comment has been minimized.

Copy link

commented Feb 14, 2019

@ajcvickers

This comment has been minimized.

Copy link
Member

commented Feb 14, 2019

@sjb-sjb Not saying those aren't useful events. They are still on the table.

@SidShetye

This comment has been minimized.

Copy link

commented May 23, 2019

Hi Arthur and Diego - can we raise the priority of the lifecycle hooks? The community demand has been very strong (30+ participants, 50+ thumbs, over 5+ years) but this item has been waiting (waiting, waiting ...) in the queue to be punted across every release. I understand the team has a challenging schedule but perhaps a swap/re-prioritization against another issue/feature would help get this long-waiting item out of the queue? Thanks

CC: @ajcvickers @divega

EDIT: More precisely, the worry is this isn't on the 3.0.0 milestone or on any plan in general.

@ajcvickers

This comment has been minimized.

Copy link
Member

commented May 24, 2019

@SidShetye Unfortunately, at this point there isn't anything that can be bumped to give this a higher priority.

@douglasg14b

This comment has been minimized.

Copy link

commented May 27, 2019

Hell, lifecycle hooks have been a community want since EF v4 in 2010.

@SidShetye

This comment has been minimized.

Copy link

commented May 28, 2019

@ajcvickers That is disappointing - and hard to believe. Why? Because looking at the 474 issues open in 3.0.0 milestone, there is only ONE. solitary. single. issue with more customer demand than this issue. Every one of the remaining 473 issues has less customer expressed demand or importance (!).

I mean your customers are literally telling you "this issue is more desired than the other 99.78% of the issues". And yet the product road-map simply tosses this aside? Even with noisy measurements, the balance is overwhelmingly off.

I believe product development should be rationally driven by the customer and markets. But this issue gives the impression that it's highly whimsical. Like: "Yeah, you customers can go take a hike, we're going to build whatever we want." On top of it, this is also nothing new (since you said "at this point") - we've been at it since 2014!

We strive to work closely but this is a disappointing project dynamic.

CC: @divega

@divega

This comment has been minimized.

Copy link
Member Author

commented May 29, 2019

@SidShetye Customer feedback is very important to us. But there are several other sources of information we use to decide what goes into each release. By the way, we made an attempt to describe the process at https://docs.microsoft.com/ef/core/what-is-new/roadmap#release-planning-process.

Besides that, this isn't really a regular issue. It is more of an "umbrella" issue that represents several individual features. Each lifecycle hook clearly should have its own priority, but because we haven't broken it down into individual issues (something I would like to do, but I haven't found the time for), we get lots of votes here.

We actually implemented some of the features that used to be tracked here (state change events) in EF Core 2.1.

You are welcome to comment here about what specific lifecycle hooks would be most valuable for you and why.

You can offer to help by contributing some of them.

You are also welcome to complain about the fact that your favorite features aren't implemented and all the customers that are tracking this issue will see it. But let me set the expectation that it is very late in the 3.0 release, and given the number of work items we have in progress and the resources we have available, it is very unlikely that we will be adding any more enhancements to the list of this release.

@SidShetye

This comment has been minimized.

Copy link

commented May 29, 2019

@divega @ajcvickers - believe it or not, we're huge fans of the EF team and respect the work coming out right from EFs early days. So much so, that at the unique intersection of ORMs and Data Security where our Crypteron products, services and IP reside, we've heavily invested and have always treated EF (till EF 6.x) as our 'golden target' that drive the designs for other ORMs we support like Java's JPA/Hibernate. We're also promoting enterprise migration to the cloud/Azure by reducing data security concerns on those workloads - these are common customers between your team and us. In fact we're an Azure Security Partner working on an even closer commercial integration. The synergies are great and we're EF proponents in general.

Mapping to some of the guiding questions on your roadmap planning process:

  • Guide 1: How many devs? => The votes here are a near landslide
  • Guide 2: Workarounds? => Our service has users across languages and libraries but without the extensibility requested here, it's hard to support EF Core users as smoothly as we would really want. Short of forking EF, there isn't a workaround.
  • Guide 4: Extensibility point? => This is one of the strongest extensibility points I can think of
  • Guide 5: Synergies? => This builds synergies with products of one of your partners (us). We in turn tie in with Azure, Key Vault, VS/Nuget and several other Microsoft technologies.

In terms of what lifecycle hooks are desired, why etc., we discussed that here last year. I hear you about challenges with time on 3.0.0. You guys know best about internal resource allocation, but perhaps 3.0.1 :) ?

Thanks
sid(at)crypteron.com

@AFDevMike

This comment has been minimized.

Copy link

commented May 29, 2019

I very much appreciate the EF teams work and am hesitant to step into what is best described as a passionate back and forth. I have one request however.

  • This 'issue' is acknowledged as having the 2nd most customer demand.
  • A counter point is, this issue is an umbrella issue whereby "Each lifecycle hook clearly should have its own priority"

Objectively, I would assert if this umbrella issue has the 2nd most customer demand, but can't be treated as a single feature request. Its worthy of the time to break into individual issues to track demand more accurately.

@divega

This comment has been minimized.

Copy link
Member Author

commented May 29, 2019

@SidShetye thanks for the pointer to #626 (comment). To give you some perspective, there were ~90 comments before that, and ~70 comments after that in this issue. That is one of the reasons it has become extremely hard to distill the comments in this issue into actionable work items that we can prioritize. I would be very grateful if you go ahead and create a new issue for the specific hooks you need. Please, try to be very specific about what you need (unfortunately, after re-reading that comment a couple of times, I am still not sure), and feel free to link to it from here.

@AFDevMike

I would assert if this umbrella issue has the 2nd most customer demand

I wonder how you are counting. In https://github.com/aspnet/EntityFrameworkCore/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-desc this appears to be in the 14th position. But as I said, the main problem is that it is impossible hard to distill what it really means in terms of actionable work items for the individual lifecycle hooks and their relative priorities.

@AFDevMike

This comment has been minimized.

Copy link

commented May 29, 2019

@divega I was counting based upon @SidShetye's assertion here: #626 (comment)

Because looking at the 474 issues open in 3.0.0 milestone, there is only ONE. solitary. single. issue with more customer demand than this issue. Every one of the remaining 473 issues has less customer expressed demand or importance (!).

And since it wasn't refuted in your direct response, I assumed it to approximate the reality. My error, apologies for noise.

@weitzhandler

This comment has been minimized.

Copy link
Contributor

commented May 29, 2019

@divega

I opened a new issue that is related to life-cycle hooks. In my scenario, I need to have a post-OnConfiguration hook, so I can call Database.Migrate. See #15846.

@SidShetye

This comment has been minimized.

Copy link

commented May 30, 2019

@divega I've created the lifecycle hooks work item issue here as you asked. Hoping it accelerates this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.