Search code examples
c#entity-frameworktransactionscopeduplicate-data

Entity Framework inserting duplicate records


I'm trying to do a couple of related insertions in a transaction and for some reason EF keeps inserting multiple duplicate records. The closest I could find here is the many-to-many issue, but that doesn't solve my problem.

Here's what I'm trying to do:

public void UploadFilesToStorage(MetadataLineCollection metadata, string outputDirectory)
    {
        using (var scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromMinutes(15)))
        using (var context = new DbEntities())
        {
            decimal newJobId = CreateNewJob(context, metadata.CommonMetadata.OriginalFileName);

            foreach (var item in metadata.Items)
            {
                var fingerprint= service.UploadFile(outputDirectory + "\\" + item.TifFileName);
                StoreFileInfo(context, newJobId, imageFingerprint, item);
            }

            var csvFingerprint = service.UploadFile(outputDirectory + "\\" + metadata.CsvFileName);
            StoreFingerprint(context, newJobId, csvFingerprint);
            CreateNewDelivery(context, newJobId);

            scope.Complete();
            context.AcceptAllChanges();
        }
    }

As you can see, I'm passing the same context to each function that's supposed to use related data. Each of those calls context.SaveChanges(false).

Still, multiple identical jobs are being created (but only the first one has the fingerprint, since the rest has different jobIds), and each metadata item is stored multiple times, too! Also, the amount of duplicates is different (for one metadata item it's 8, for another it's 3, etc...)

Am I missing something here?


Solution

  • According to the MSDN Documentation for the acceptChangesDuringSave parameter of ObjectContext.SaveChanges

    If true, the change tracking on all objects is reset after SaveChanges(Boolean) finishes. If false, you must call the AcceptAllChanges method after SaveChanges(Boolean)

    This should mean that all objects in the change tracker will still have the state of Modified or Added, and subsequent calls to SaveChanges() will persist them again.

    Try either removing the false parameter, or don't call SaveChanges() at all inside your various methods and call it once later on