I am comparing two same objects by implementing an IEquatable interface on the object. If they are not equal, then update the DB; otherwise, leave it as it is. Here the context is i need to update the table with the data coming from an excel sheet and compare the data and update only when there is a data change.
Below is the code for the same
var constructionMaterialTypes = package.GetObjectsFromSheet<ConstructionMaterialTypeExcelDto>(ConstructionDataSheetNames.CONSTRUCTION_MATERIAL_TYPE,
ConstructionDataTableNames.ConstructionMaterialType);
var materialTypes = new List<ConstructionMaterialType>();
foreach (var materialType in constructionMaterialTypes)
{
var materialTypeId = GetGuidFromMD5Hash(materialType.name);
List<string> materialTypeNotes = new();
if (!string.IsNullOrEmpty(materialType.notes))
{
materialTypeNotes.Add(materialType.notes);
}
var existingMaterialType = ctx.ConstructionMaterialTypes.SingleOrDefault(cm => cm.Id == materialTypeId);
var constructionMaterialType = new ConstructionMaterialType
{
Id = materialTypeId,
Name = materialType.name,
NotesHTML = materialTypeNotes
};
if (existingMaterialType != default)
{
if (existingMaterialType != constructionMaterialType) // Object comparison happening here
{
existingMaterialType.Name = materialType.name;
existingMaterialType.NotesHTML = materialTypeNotes;
}
}
else
{
materialTypes.Add(constructionMaterialType);
}
}
and then below is the actual class where I am implementing Iequatable interface
public sealed class ConstructionMaterialType : IIdentity<Guid>, IEquatable<ConstructionMaterialType>
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public List<string> NotesHTML { get; set; }
public bool Equals(ConstructionMaterialType other)
{
if (other is null)
return false;
return this.Id == other.Id
&& this.Name == other.Name
&& this.NotesHTML == other.NotesHTML;
}
public override bool Equals(object obj) => Equals(obj as ConstructionMaterialType);
public override int GetHashCode()
{
int hash = 19;
hash = hash * 31 + (Id == default ? 0 : Id.GetHashCode());
hash = hash * 31 + (Name == null ? 0 : Name.GetHashCode(StringComparison.OrdinalIgnoreCase));
hash = hash * 31 + (NotesHTML == null ? 0 : NotesHTML.GetHashCode());
return hash;
}
}
this condition existingMaterialType != constructionMaterialType
is always true even if both objects are holding the same values, and I have attached the images as well for reference purposes
I am not sure where I am doing wrong in the above code. Could anyone please point me in the right direction? Many thanks in advance
You did not override the !=
operator, but you can use !existingMaterialType.Equals(constructionMaterialType)
instead.
this.NotesHTML == other.NotesHTML
will do a reference comparison of the two list, so even if both contain excactly the same strings, it will return false
is the two lists are different instances. You might want to use this.NotesHTML.SequenceEqual(other.NotesHTML)
instead (might need sone adaptation if NotesHTML
can be null
).
Note: GetHashCode
must deliver the same result for all objects that compare equal. So if you change anything in the Equals
method, you probably also have to change GetHashCode
. As it is not necessary that objects that compare non-equal have different hash codes, it is an option to just not take into account some properties. Here: just omit the line with NotesHTML
.