Reputation: 13159
I've extended a class in order to add a last modified timestamp to a record if there are material changes being made to it. This was done with code similar to this.
Here's my problem. SaveChanges()
is firing for both changes, but the second one isn't getting into the loop: no objects are detected as needing changes.
However, the record does get updated by EF through the base.SaveChanges() call.
Here's the extension to MasterTable:
namespace AuditTestEF
{
public interface IHasAuditing
{
DateTime LastModifiedOn { get; set; }
int LastModifiedBy { get; set; }
}
public partial class MasterTable : IHasAuditing
{
}
public class AuditTestEntitiesWithAuditing : AuditTestEntities
{
public int TestingUserIs = 1;
public override int SaveChanges()
{
foreach (ObjectStateEntry entry in (this as IObjectContextAdapter)
.ObjectContext
.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
{
// This loop is entered the first time, but not the second
if (entry.IsRelationship) continue;
var lastModified = entry.Entity as IHasAuditing;
if (lastModified == null) continue;
lastModified.LastModifiedOn = DateTime.UtcNow;
lastModified.LastModifiedBy = TestingUserIs;
}
return base.SaveChanges();
}
}
}
And here's the test harness:
[TestMethod]
public void TestMethod1()
{
MasterTable mtOriginal;
using (var audit = new AuditTestEntitiesWithAuditing())
{
var message = "Hello";
audit.TestingUserIs = 1;
mtOriginal = new MasterTable {TextField = message};
audit.MasterTable.Add(mtOriginal);
audit.SaveChanges();
// This test passes, TestingUser is set in the override
Assert.IsTrue(mtOriginal.LastModifiedBy == audit.TestingUserIs);
}
using (var audit = new AuditTestEntitiesWithAuditing())
{
var mt = audit.MasterTable.Find(mtOriginal.MasterTableId);
mt.TextField = "Goodbye";
audit.TestingUserIs = 4;
audit.SaveChanges();
// This test fails, the record is written with "Goodbye" but
// GetObjectStateEntries(EntityState.Added | EntityState.Modified) has no entries.
Assert.IsTrue(mt.LastModifiedBy == audit.TestingUserIs);
}
}
There's no other code. There's no weird turning off/on the entity tracking or anything. WYSIWYG.
What am I missing? How is the clearly modified object being missed by the check for Modified?
Upvotes: 4
Views: 908
Reputation: 13159
Annnd... answered my own question, of course, after talking to the duck.
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
This fixes everything. Thank you for your attention, I hope this helps someone else.
Upvotes: 1