EF Core 5.x and later, cannot use Change-tracking proxies with EntityFrameworkDataProvider
See original GitHub issueDescribe the bug Since EF Core 5.0, Microsoft has put built-in support for change-tracking proxies via the Microsoft.EntityFrameworkCore.Proxies package, as described here: https://docs.microsoft.com/en-us/ef/core/change-tracking/change-detection#change-tracking-proxies
When trying to use change-tracking proxies with the EntityFrameworkDataProvider, I get an exception on trying to save changes to the database because the object instance of the audit entity was created in Audit.NET using Activator.CreateInstance instead of using the DbContext’s CreateProxy. Specifically the exception is as follows:
System.InvalidOperationException: 'The entity type 'AuditLog' is configured to use the 'ChangingAndChangedNotifications' change tracking strategy, but does not implement the required 'INotifyPropertyChanging' interface. Implement 'INotifyPropertyChanging' on 'AuditLog' or use a different change tracking strategy.'
To Reproduce (This is just a pretty bare bones set of classes, which I hope should be enough to demonstrate the problem.)
public class AuditLog
{
public int Id { get; set; }
public DateTime DateTime { get; set; }
}
public class Test
{
public int Id { get; set; }
public string TestString { get; set; }
}
public class MyDbContext : AuditDbContext
{
public DbSet<Test> Tests => this.Set<Test>();
// Assume there is an OnConfiguring here that calls UseChangeTrackingProxies() on the optionsBuilder
}
class Program
{
static void Main()
{
_ = Audit.Core.Configuration.Setup().UseEntityFramework(ef => ef.
UseDbContext<MyDbContext>().
AuditTypeMapper(t => typeof(AuditLog)).
AuditEntityAction<AuditLog>((ev, ent, auditEntity) => auditEntity.DateTime = DateTime.Now).
IgnoreMatchedProperties(true)
);
using var context = new MyDbContext();
_ = context.Test.Add(context.CreateProxy<Test>(test => test.TestString = "Test"));
_ = context.SaveChanges(); // <-- Exception happens when this is called
}
}
Expected behavior Audit.NET’s EntityFrameworkDataProvider should detect that the DbContext uses change-tracking proxies and change how it creates the audit entity for the database.
Libraries (specify the Audit.NET extensions being used including version):
- Audit.EntityFramework.Core: 19.0.0
- Microsoft.EntityFrameworkCore.Proxies: 5.0.12 (I suspect that the type of database being used won’t matter)
Target .NET framework:
- .NET 5.0 (but I suspect the framework won’t matter, what matters is if EF Core 5.x or later is being used)
Additional context When not using change-tracking proxies, everything works as expected.
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
I can confirm when using
AuditEntityCreator
that things work perfectly as expected, thank you for making this update. 😄After I got to work, I thought about this a little, perhaps you could have 2 signatures for that factory mapper, one as you suggested which would work for the single-table audit but another that provides both the context and the audit entity type (from the audit type mapper). CreateProxy has an overload which is non-generic and takes the
Type
as an argument.