DbEntityValidationException causes AuditEntityAction StackOverflowException
See original GitHub issueI’m likely doing something incorrectly here but I’ve narrowed down an issue when attempting to save an entity with validation errors. If the source (Foo) has validation errors it will spur a stack overflow of trying to create audit entries (FooAudit).
Environment: Visual Studio 2017 Community .NET Framework 4.7.1 Audit.NET 11.0.7 Audit.EntityFramework 11.0.7 EntityFramework 6.2.0
Here’s the simplest example I could create to demonstrate the issue:
Setup:
Audit.Core.Configuration.Setup()
.UseEntityFramework(config =>
{
config
.AuditTypeMapper(typeName => Type.GetType(typeName + "Audit"))
.AuditEntityAction((ev, ent, audEnt) =>
{
((dynamic)audEnt).Username = "test";
});
});
Entities/Context:
public class Foo
{
public int Id { get; set; }
[Required]
public string Bar { get; set; }
public string Car { get; set; }
}
public class FooAudit
{
public int Id { get; set; }
public string Bar { get; set; }
public string Username { get; set; }
}
public class AuditNetTestContext : Audit.EntityFramework.AuditIdentityDbContext<XUser>
{
public DbSet<Foo> Foos { get; set; }
public DbSet<FooAudit> FooAudits { get; set; }
public AuditNetTestContext():base("DefaultConnectionString")
{
}
}
Run:
using (var db = new AuditNetTestContext())
{
db.Foos.Add(new Foo());
db.SaveChanges();
}
Stack:
AuditNetTest.dll!AuditNetTest.Data.Orm.EntityFramework.EntityFrameworkAuditDataProvider.Initialize.AnonymousMethod__2_2(Audit.Core.AuditEvent ev, Audit.EntityFramework.EventEntry ent, object audEnt) Line 37
at C:\@Dev\AuditNet\AuditNetSetup.cs(37)
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Audit.EntityFramework.dll!Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(Audit.Core.AuditEvent auditEvent)
Audit.NET.dll!Audit.Core.AuditScope.SaveEvent(bool forceInsert)
Audit.NET.dll!Audit.Core.AuditScope.Save()
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveScope(Audit.EntityFramework.IAuditDbContext context, Audit.Core.AuditScope scope, Audit.EntityFramework.EntityFrameworkEvent event)
Audit.EntityFramework.dll!Audit.EntityFramework.DbContextHelper.SaveChanges(Audit.EntityFramework.IAuditDbContext context, System.Func<int> baseSaveChanges)
Audit.EntityFramework.dll!Audit.EntityFramework.AuditIdentityDbContext<AuditNetTest.Data.Model.Identity.AUser>.SaveChanges()
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (4 by maintainers)
Top Results From Across the Web
StackOverflow exception on SaveChanges if ...
I'm running into stackoverflow exception when trying to call saveChanges and hitting a DbEntityValidationException.
Read more >DbEntityValidationException - How can I easily tell what ...
The easiest solution is to override SaveChanges on your entities class. You can catch the DbEntityValidationException , unwrap the actual ...
Read more >DbEntityValidationException Class (System.Data.Entity. ...
Exception thrown from SaveChanges() when validating entities fails.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
ok… will fix this soon.
Bug is here, sorry: https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.EntityFramework/Providers/EntityFrameworkDataProvider.cs#L83
That line determines if the context is an Audited Context by checking if it inherits from
AuditDbContext
, in which case, it saves the entity bypassing the auditing mechanism… But theAuditIdentityDbContext
doesn’t inherit from AuditDbContext, so the bypassing mechanism is broken for them.This was fixed on version v11.0.8, please upgrade and re-test.
Feel free to re-open if you’re still having problems.