I have a method, GetItemCode, which is passed a barcode string and returns an StkBarcode object.
GetItemCode is a method in Class2. It has an ImmutableList of reference data (called listStkBarcodes, in the code block) that it looks through for a matching barcode. The problem is that listStkBarcodes is getting edited by actions in a different class.
private ImmutableList<StkBarcode> listStkBarcodes;
The code never edits that ^ list, listStkBarcodes.
Here are the EF Frameworks in the solution:
Once GetItemCode returns the matching StkBarcode (which has an ItemCode property) to the calling method, the code sometimes edits that ItemCode. That editing is done in Class1.
Here is how the results from GetItemCode are handled in the calling method.
StkBarcode objStkBc = await helper.GetItemCode(strBarcode, TheShippers, ShipperMfCodesList);
The value of objStkBc.ItemCode is what the logic sometimes edits. To me that object, objStkBc, is completely independent of the ImmutableList of reference data in Class2.
The next time GetItemCode is passed the same barcode, the method finds the matching StkBarcode in listStkBarcodes, but this time the corresponding ItemCode, has the edited value of ItemCode. – the value that the method in Class1 gave it.
So the ImmutableList got edited.
Here is how the ImmutableList gets populated in Class2:
public async Task<ImmutableList<StkBarcode>> GetReadOnlyStkBarcodes()
{
ImmutableList<StkBarcode> TheList = ImmutableList.Create<StkBarcode>();
List<StkBarcode> theList = await _context.StkBarcodes.Where(b => b.ItemCode != null
&& b.Barcode != null).ToListAsync();
TheList = theList.ToImmutableList();
return TheList;
}
Regarding the ToImmutableList method above: I don’t see it in the MS documentation, however if I do F12 on it (in Visual Studio) it is there in the System.Collections.Immutable namespace.
Here is the StkBarcode class, in case this helps:
using System;
using System.Collections.Generic;
namespace MainModels.MainModels
{
public partial class StkBarcode
{
public StkBarcode()
{
ScannedItems = new HashSet<ScannedItem>();
}
public StkBarcode(string itemCode, string custCode)
{
ItemCode = itemCode;
CustCode = custCode;
BarcodeId = 0;
Count = 0; DefaultLock = false; RequireLotCode = false; CreatedDatetime = DateTime.Now;
ScannedItems = new HashSet<ScannedItem>();
}
public int BarcodeId { get; set; }
public string? Barcode { get; set; }
public string? ItemCode { get; set; }
public string? CustCode { get; set; }
public short? MobileDeviceId { get; set; }
public int Count { get; set; }
public int? CreateBy { get; set; }
public string? OldItemCode { get; set; }
public bool? IsSubstitute { get; set; }
public bool DefaultLock { get; set; }
public bool RequireLotCode { get; set; }
public bool LotCode { get; set; }
public bool? Deleted { get; set; }
public DateTime CreatedDatetime { get; set; }
public DateTime? ModifiedDatetime { get; set; }
public byte[]? RowVersion { get; set; } = null!;
public virtual ICollection<ScannedItem>? ScannedItems { get; set; }
}
}
I need the ImmutableList, listStkBarcodes, to never get edited. Ideas?
2
Answers
Here is the workaround I ended up with.
I created a new type that is identical to StkBarcode, lets call it StkBarcodeCopy
I put the reference data that had been going to listStkBarcodes in a list of that new type, List
the code searches in ListStkBarcodeCopy for the matching item it wants
if the code finds a matching item we convert the StkBarcodeCopy item to a StkBarcode
then the code does its thing with THAT object
the code edits the object as I describe above, but the reference data never gets edited
Immutable collections cannot be modified. However, the items they contain may be modified. It sounds like you have two different parts of the code that are accessing the same
StkBarcode
instance concurrently.The only way to fix this is to manage the concurrent access of the
StkBarcode
instance. Either make that type immutable, or protect it with alock
.