我允许用户将一些数据下载到csv。然后,他们可以编辑一些列,然后将其上传。我需要一种快速有效的方式来比较相似对象之间的某些列,以查看更改的内容。比较2列表对象的最快方法
目前笔者从DB拉的原始数据,并使它成为一个列表,所以这一切都在内存中。大约有10万个物品,所以没那么糟糕。这部分不到一秒钟。然后我加载到csv文件并将其放入列表中。两个列表都具有相同的类类型。
然后我遍历CSV数据(因为他们可能删除了一些行,他们并没有改变,但他们仍然可以有很大的变化行)。对于csv列表中的每一行,我查询来自数据库的列表以查找该对象。现在我将csv对象和数据库中的对象作为相同的结构。然后,我通过自定义对象比较函数运行它,查看某些列以查看是否有任何更改。
如果事情的确发生了变化我要验证,他们进入的是通过查询一个有效的值该列另一个参考列表。如果无效,我将它写入例外列表。最后如果没有例外,我保存到db。如果有例外,我不保存任何内容,并向他们显示错误列表。
细节比较提供的列清单和老VS,改变了新的价值。我需要这个来查询引用列表,以确保新值在我进行更改之前是有效的。这是相当低效的,但它给用户提供了非常有价值的可能是上传问题的详细信息。
这是非常缓慢的。我正在寻找加快速度的方法,同时仍然能够向用户提供有关它为什么可能失败的详细信息,以便他们能够纠正它。
// get all the new records from the csv
var newData = csv.GetRecords<MyTable>().ToArray();
// select all data from database to list
var origData = ctx.MyTable.Select(s => s).ToList();
// look for any changes in the new data and update the database. note we are looping over the new data so if they removed some data from the csv file it just won't loop over those and they won't change
foreach (var d in newData)
{
// find data so we can compare between new (csv) and current (from db) to see what possibly changed
var oData = (from o in origData
where o.id == d.id
select o).FirstOrDefault();
// only the columns in the updatableColumns list are compared
var diff = d.DetailedCompare(oData, comparableColumns.ToList());
if (diff.Count > 0)
{
// even though there are differences between the csv record and db record doesn't mean what the user input is valid. only existing ref data is valid and needs to be checked before a change is made
bool changed = false;
// make a copy of this original data and we'll check after if we actually were able to make a change to it (was the value provided valid)
var data = CopyRecord(oData);
// update this record's data fields that have changed with the new data
foreach (var v in diff)
{
// special check for setting a value to NULL as its always valid to do this but wouldn't show up in ref data to pass the next check below
if (v.valA == null)
{
oData.GetType().GetProperty(v.Prop).SetValue(oData, v.valA);
oData.UpdatedBy = user;
oData.UpdatedDate = DateTime.Now;
changed = true;
}
// validate that the value for this column is in the ref table before allowing an update. note exception if not so we can tell the user
else if (refData[v.Prop].Where(a => a.value == v.valA.ToString()).FirstOrDefault() != null)
{
// update the current objects values with the new objects value as it changed and is a valid value based on the ref data defined for that column
oData.GetType().GetProperty(v.Prop).SetValue(oData, v.valA);
oData.UpdatedBy = user;
oData.UpdatedDate = DateTime.Now;
changed = true;
}
else
{
// the value provided isn't valid for this column so note this to tell the user
exceptions.Add(string.Format("Error: ID: {0}, Value: '{1}' is not valid for column [{2}]. Add the reference data if needed and re-import.", d.id, v.valA, v.Prop));
}
}
// we only need to reattach and save off changes IF we actually changed something to a valid ref value and we had no exceptions for this record
if (changed && exceptions.Count == 0)
{
// because our current object was in memory we will reattached it to EF so we can mark it as changed and SaveChanges() will write it back to the DB
ctx.MyTable.Attach(oData);
ctx.Entry(oData).State = EntityState.Modified;
// add a history record for the change to this product
CreateHistoryRecord(data, user);
}
}
}
// wait until the very end before making DB changed. we don't save anything if there are exceptions or nothing changed
if (exceptions.Count == 0)
{
ctx.SaveChanges();
}
将新数据插入临时表并使用SQL过滤原始数据? –