-1

currently i am trying to solve the riddle of EntityFramework magically altering my property during SaveChanges

so for some reason, the following snipped decides to alter the value of ReceiptEntry to always 10 or 12

void HandleReceipt(DBContext cntxt, Receipt receipt, ...)
{
    [...]
    var receiptEntries = receipt.GetEntries(cntxt);
    var receiptEntriesItem = from q in cntxt.Items
                             where ...
                             select new { ... };
    var receiptEntriesItemDictionary = receiptEntriesItem.ToDictionary(...);
    [...]
    while (...)
    {
        [...]
        var receiptEntry = receiptEntriesItemDictionary[it.ItemFK];
        [...]
        foreach (var kvp in ...)
        {
            var sle = usedStorages.First((sl) => sl.Id == kvp.Key);
            entry = new PickListEntry
            {
                Parent = receipt.PickList,
                Amount = kvp.Value,
                ReceiptEntry = receiptEntry, // receiptEntry is the instance with eg. Id 60
                StorageLocation = sle
            };
            sle.Stock = new Stock { AmountAvailable = 0, ItemFK = receiptEntry.ItemFK };
            var createdEntry = cntxt.PickListEntries.Add(entry);
            cntxt.SaveChanges(); // ReceiptEntry property gets modified in here to the instance with 10 or 12
            [...]
        }
        [...]
    }
}

by now, i am clueless of why this may happens.

The 10 & 12 are entries that do not relate to the currenly worked on receipt in any way (however, they are loaded in the current cntxt and processed in another call to HandleReceipt)

I already tripple checked that theese two never are assigned anywhere (entry is only ever used right there and never afterwards in here) and checked when they get changed (The famous [External Code] is exactly one below the setter)

Anybody capable of telling me why this is happening and how to fix it? Spinning up another DBContext is no option as this is happening inside a transaction (cntxt.Database.BeginTransaction()) (aka: something fails means everything needs to be rolled back)

X39
  • 789
  • 6
  • 22
  • 1
    It would be awesome to see a [mcve]. – mjwills Jun 11 '19 at 12:59
  • updated the code snippet above. stuff like `ItemFK` is irrelevant to this issue (double checked on my code base too) also noticed that this is happening on every second item (1, 3, 5, 7, ... are affected by this) – X39 Jun 11 '19 at 13:07
  • https://stackoverflow.com/questions/25182823/memberwiseclone-on-object-that-contain-dictionary-does-not-work is likely the best duplicate. – mjwills Jun 11 '19 at 13:39

1 Answers1

0

The actual problem was inside of a little method named FlatCopy() somebody implemented careless ...

// Problematic, as there is a collection in here that gets refered to
public ReceiptEntry FlatCopy() => this.MemberwiseClone() as ReceiptEntry;

// Totally fine as we create a new collection
public ReceiptEntry FlatCopy()
{
    var copy = this.MemberwiseClone() as ReceiptEntry;
    copy.PicklistEntries = new ObservableCollection<PickListEntry>();
    copy.Id = 0;
    return copy;
}

Actual reasoning for the above "strange" behavior then was, that this got added to the other ReceiptEntry's PicklistEntries collection which then caused the update of the PickListEntry.ReceiptEntryFK field.

TL;DR: Dear fellow user, check your copy methods wether or not they actually do create separate instances of your collections.

X39
  • 789
  • 6
  • 22