Coder Social home page Coder Social logo

entityframeworkplus / entityframework.triggers Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nickstrupat/entityframework.triggers

0.0 1.0 0.0 823 KB

Adds events for entity inserting, inserted, updating, updated, deleting, and deleted

C# 100.00%

entityframework.triggers's Introduction

EntityFramework.Triggers

Add triggers to your entities with insert, update, and delete events. There are three events for each: before, after, and upon failure.

EF version .NET support NuGet package
6.1.3 >= Framework 4.6.1 NuGet Status
Core 2.0 >= Framework 4.6.1 || >= Standard 2.0 NuGet Status

This repo contains the code for both the EntityFramework and EntityFrameworkCore projects.

Basic usage

To use triggers on your entities, simply have your DbContext inherit from DbContextWithTriggers. If you can't change your DbContext inheritance chain, you simply need to override your SaveChanges... as demonstrated below

public abstract class Trackable {
	public DateTime Inserted { get; private set; }
	public DateTime Updated { get; private set; }

	static Trackable() {
		Triggers<Trackable>.Inserting += entry => entry.Entity.Inserted = entry.Entity.Updated = DateTime.UtcNow;
		Triggers<Trackable>.Updating += entry => entry.Entity.Updated = DateTime.UtcNow;
	}
}

public class Person : Trackable {
	public Int64 Id { get; private set; }
	public String Name { get; set; }
}

public class Context : DbContextWithTriggers {
	public DbSet<Person> People { get; set; }
}

As you may have guessed, what we're doing above is enabling automatic insert and update stamps for any entity that inherits Trackable. Events are raised from the base class/interfaces, up to the events specified on the entity class being used. It's just as easy to set up soft deletes (the Deleting, Updating, and Inserting events are cancellable from within a handler, logging, auditing, and more!).

Manual overriding to enable triggers

If you can't easily change what your DbContext class inherits from (ASP.NET Identity users, for example), you can override your SaveChanges... methods to call the SaveChangesWithTriggers... extension methods. Alternatively, you can call SaveChangesWithTriggers... directly instead of SaveChanges... if, for example, you want to control which changes cause triggers to be fired.

class YourContext : DbContext {
	// Your usual DbSet<> properties

	#region If you're targeting EF 6
	public override Int32 SaveChanges() {
		return this.SaveChangesWithTriggers(base.SaveChanges);
	}
	public override Task<Int32> SaveChangesAsync(CancellationToken cancellationToken) {
		return this.SaveChangesWithTriggersAsync(base.SaveChangesAsync, cancellationToken);
	}
	#endregion

	#region If you're targeting EF Core
	public override Int32 SaveChanges() {
		return this.SaveChangesWithTriggers(base.SaveChanges, acceptAllChangesOnSuccess: true);
	}
	public override Int32 SaveChanges(Boolean acceptAllChangesOnSuccess) {
		return this.SaveChangesWithTriggers(base.SaveChanges, acceptAllChangesOnSuccess);
	}
	public override Task<Int32> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)) {
		return this.SaveChangesWithTriggersAsync(base.SaveChangesAsync, acceptAllChangesOnSuccess: true, cancellationToken: cancellationToken);
	}
	public override Task<Int32> SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken)) {
		return this.SaveChangesWithTriggersAsync(base.SaveChangesAsync, acceptAllChangesOnSuccess, cancellationToken);
	}
	#endregion
}

#region If you're calling `SaveChangesWithTriggers...` directly (instead of an overridden `SaveChanges...`)
dbContext.SaveChangesWithTriggers(dbContext.SaveChanges);
dbContext.SaveChangesWithTriggersAsync(dbContext.SaveChangesAsync);
#endregion

Longer example (targeting EF6 for now)

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EntityFramework.Triggers;

namespace Example {
	public class Program {
		public abstract class Trackable {
			public virtual DateTime Inserted { get; private set; }
			public virtual DateTime Updated { get; private set; }

			static Trackable() {
				Triggers<Trackable>.Inserting += entry => entry.Entity.Inserted = entry.Entity.Updated = DateTime.UtcNow;
				Triggers<Trackable>.Updating += entry => entry.Entity.Updated = DateTime.UtcNow;
			}
		}

		public abstract class SoftDeletable : Trackable {
			public virtual DateTime? Deleted { get; private set; }

			public Boolean IsSoftDeleted => Deleted != null;
			public void SoftDelete() => Deleted = DateTime.UtcNow;
			public void SoftRestore() => Deleted = null;

			static SoftDeletable() {
				Triggers<SoftDeletable>.Deleting += entry => {
					entry.Entity.SoftDelete();
					entry.Cancel = true; // Cancels the deletion, but will persist changes with the same effects as EntityState.Modified
				};
			}
		}

		public class Person : SoftDeletable {
			public virtual Int64 Id { get; private set; }
			public virtual String FirstName { get; set; }
			public virtual String LastName { get; set; }
		}

		public class LogEntry {
			public virtual Int64 Id { get; private set; }
			public virtual String Message { get; set; }
		}

		public class Context : DbContextWithTriggers {
			public virtual DbSet<Person> People { get; set; }
			public virtual DbSet<LogEntry> Log { get; set; }
		}
		internal sealed class Configuration : DbMigrationsConfiguration<Context> {
			public Configuration() {
				AutomaticMigrationsEnabled = true;
			}
		}

		static Program() {
			Triggers<Person, Context>.Inserting += e => {
				e.Context.Log.Add(new LogEntry { Message = "Insert trigger fired for " + e.Entity.FirstName });
				Console.WriteLine("Inserting " + e.Entity.FirstName);
			};
			Triggers<Person>.Updating += e => Console.WriteLine("Updating " + e.Entity.FirstName);
			Triggers<Person>.Deleting += e => Console.WriteLine("Deleting " + e.Entity.FirstName);
			Triggers<Person>.Inserted += e => Console.WriteLine("Inserted " + e.Entity.FirstName);
			Triggers<Person>.Updated += e => Console.WriteLine("Updated " + e.Original.FirstName);
			Triggers<Person>.Deleted += e => Console.WriteLine("Deleted " + e.Entity.FirstName);
		}
		
		private static void Main(String[] args) => Task.WaitAll(MainAsync(args));

		private static async Task MainAsync(String[] args) {
			using (var context = new Context()) {
				context.Database.Delete();
				context.Database.Create();

				var log = context.Log.ToList();
				var nickStrupat = new Person {
					FirstName = "Nick",
					LastName = "Strupat"
				};

				context.People.Add(nickStrupat);
				await context.SaveChangesAsync();

				nickStrupat.FirstName = "Nicholas";
				context.SaveChanges();
				context.People.Remove(nickStrupat);
				await context.SaveChangesAsync();
			}
		}
	}
}

See also

Contributing

  1. Create an issue
  2. Let's find some point of agreement on your suggestion.
  3. Fork it!
  4. Create your feature branch: git checkout -b my-new-feature
  5. Commit your changes: git commit -am 'Add some feature'
  6. Push to the branch: git push origin my-new-feature
  7. Submit a pull request :D

History

Commit history

License

MIT License

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.