This project is read-only.
3
Vote

Everything is tracked more than once.

description

I have done my best to follow all the steps properly, but i am sure from the results that still i have done something wrong.

I create a new object and i call SubmitChanges. I can see my new object saved in my database. Then i check the AuditRecords table and i see two entries for my object. In my application i still have the form open so i make a change and press save again. Now the AuditRecords have three new entries. I do an other change in my object and i press save. My AuditRecords table has four new entries and if i continue the changes and saves i get more and more entries in my AuditRecords table.

Can anyone point me to the right direction what is going on?

Thank you.

comments

jrshannon wrote Jul 28, 2009 at 11:56 PM

Hi --

I think I found that bug while doing some of my own testing. At least for me, it's caused when you use .SubmitChanges() more than once and you've inserted something.

If you can, only .SubmitChanges() once. If that's not feasible (it's not in my code -- I need to get a primary key then do some updates), then try running it through the debugger, pause for a few minutes after the first .SubmitChanges(), then continue. See if there's an equal time difference between the AuditRecords.

This is due to the code queuing the Inserts (in order to get the primary key), then looping through the queue to add to the database. The queue isn't deleted, and thus those inserts stay around until the next call.

To fix, add:

_queuedRecords.Clear();

after

foreach (AuditedEntity record in _queuedRecords)
        {
            record.UpdateKeys();
            InsertAuditRecordToDatabase(record);
        }
in AuditableDataContext.cs

As best as I can tell, this is a pure bug and I'm not breaking anything.

Please update this thread with whether or not this is the solution for you. I need to use this in production and want to make sure I've got all the bugs quashed.

infoCENTER wrote Jul 29, 2009 at 2:00 PM

Hi jrshannon.

Thank you for your respond. I have downloaded the source from the download area and opened the AuditableDataContext.cs
I think that you refer to the overriden SubmitChanged routine. In my source code it is the below.
    public override void SubmitChanges(ConflictMode failureMode)
    {
        DefaultAuditDefinitions();


        AuditProcessor processor = new AuditProcessor(this);
        processor.Process();

        base.SubmitChanges(failureMode);

        foreach (EntityAuditRecord record in _queuedRecords)
        {
            // New entities (inserts) will have a PK of 0 until LINQ submits changes to the DB and retrieves the real PK,
            // so we need to update the Insert Audit record with the real PK
            if (record.Action == AuditAction.Insert)
            {
                int pk = (int)record.KeySelector.Compile().DynamicInvoke(record.Entity);
                if (record.EntityTableKey == 0)
                    record.EntityTableKey = pk;
            }

            InsertAuditRecordToDatabase(record);
        }

        // Submit all audits to the db, continue processing even if Auditing records fail
        base.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
Now when i add the line of code you wrote me
    public override void SubmitChanges(ConflictMode failureMode)
    {
        DefaultAuditDefinitions();


        AuditProcessor processor = new AuditProcessor(this);
        processor.Process();

        base.SubmitChanges(failureMode);

        foreach (EntityAuditRecord record in _queuedRecords)
        {
            // New entities (inserts) will have a PK of 0 until LINQ submits changes to the DB and retrieves the real PK,
            // so we need to update the Insert Audit record with the real PK
            if (record.Action == AuditAction.Insert)
            {
                int pk = (int)record.KeySelector.Compile().DynamicInvoke(record.Entity);
                if (record.EntityTableKey == 0)
                    record.EntityTableKey = pk;
            }

            InsertAuditRecordToDatabase(record);
        }

        _queuedRecords.Clear

        // Submit all audits to the db, continue processing even if Auditing records fail
        base.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
my compiler generates an error which is :
Error 1 Only assignment, call, increment, decrement, and new object expressions can be used as a statement C:\Documents and Settings\George Parissis\My Documents\Apps\Programming\LINQ Audit Trail\Doddle.Linq.Audit-Source\Doddle.Linq.Audit\LinqToSql\AuditableDataContext.cs 132 13 Doddle.Linq.Audit

Thank you.

jrshannon wrote Jul 29, 2009 at 2:47 PM

well. it appears you're missing the (); at the end of Clear

Other than that, you should confirm that it compiles first before making the change.

Also, if you step through your own code, and pause for a few minutes before each call to SubmitChanges(), you should be able to, at least, confirm if this is the same cause.

jrshannon wrote Aug 9, 2009 at 11:21 PM

Please note that I found another potential reason why calling SubmitChanges() more than once could cause mutliple entries. See http://doddleaudit.codeplex.com/WorkItem/View.aspx?WorkItemId=2398

mhidinger wrote Dec 16, 2009 at 4:23 PM

Hello,

Thank you for reporting this issue. As discussed above and in another thread, this has been tracked down thanks to help from all of you and has been fixed in the upcoming release, which should be ready in a week or so.

-Matt

yosel wrote Jul 19, 2010 at 11:38 PM

this post http://doddleaudit.codeplex.com/workitem/2398 takes care of the issue.