我允許用戶將一些數據下載到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過濾原始數據? –