我有用于检查记录是否存在的代码,如果不存在,它将插入该记录。 问题是它有时会失败。 它是从消息队列中提取的。 我已经做了我能想到的所有事情,但是在某种程度上,它是在检查之后,在创建新的“线程”(我假设)上创建记录的。
错误在try / catch循环中-可以工作,但我想知道如何避免它首先发生。 我在做什么错,或者我能做得更好?
代码从这样开始:
public class Functions
{
// This function will get triggered/executed when a new message is written
// on an Azure Queue called queue.
public static void ProcessQueueMessage([QueueTrigger("stops-to-import-to-mobile")] string message, TextWriter log)
{
这里剩下的代码...然后麻烦开始了
mobileEntities mdbPcs = new mobileEntities(); //get a new context for the below
//now go create all the pcs for this stop.
var stopPieces = (from sp in db.Stop_Items where sp.stop_detail_id == stop.Id select sp).ToArray();
//get the count of the current pcs for the enxt stop
int mobilePcCount = (from s in mdbPcs.mobile_Item_Detail where s.mobile_stops_id == mstopId select s.Id).Count();
if (mobilePcCount != stopPieces.Count()) //if the piece count is the same already then no need to go through the loop
{
foreach (var item in stopPieces)//step through the items one at a time
{
int seek = (from s in mdbPcs.mobile_Item_Detail
where s.mobile_stops_id == mstopId &&
s.unique_scan_code == item.item_detail.unique_scan_code
select s.Id).FirstOrDefault();
if (seek == 0) //if we do not already have the item create it
{
mobile_Item_Detail newItem = new mobile_Item_Detail();
newItem.item_description = item.item_detail.item_description;
newItem.LOB_item_detail_id = item.item_detail.Id;
newItem.mobile_stops_id = mstopId;
newItem.dt_seq_no = item.item_detail.dt_item_seq_no;
newItem.unique_scan_code = item.item_detail.unique_scan_code;
mdbPcs.mobile_Item_Detail.Add(newItem);
try
{
mdbPcs.SaveChanges();
}
catch (Exception ex)
{
if (ex.InnerException.InnerException.Message.Contains("UNIQUE KEY")) //WTH -- Why does this keep happening...how do I fix this??!
{
Console.WriteLine($"{DateTime.Now}Unique Contraint {message} {newItem.unique_scan_code} for stop {newItem.mobile_stops_id}");
//item was already created by another thread so continue the foreach loop (I guess?!)
continue;
}
throw;
}
}
}
}
答案 0 :(得分:0)
我假设mobile_Item_Detail
具有代表身份PK的Id属性,并且mstopid
是与父代的FK关系。在那种情况下,我将对实体集合进行所有更改,然后在foreach之外调用save更改。这样,DbContext可以一次处理所有ID,因为它可以通过ChangeTracker知道所有更改,并且可以在单个db调用中执行保存。您还可以将操作包装在事务中,以在发生错误时轻松回滚更改。我还将操作包含在using语句中,以确保关闭数据源的连接(请参见here)。
using (var mdbPcs = new mobileEntities ()) //get a new context for the below
{
//now go create all the pcs for this stop.
var stopPieces = (from sp in db.Stop_Items where sp.stop_detail_id == stop.Id select sp).ToArray ();
//get the count of the current pcs for the enxt stop
var mobilePcQuery = (from s in mdbPcs.mobile_Item_Detail where s.mobile_stops_id == mstopId select s.Id);
int mobilePcCount = mobilePcQuery.Count ();
if (mobilePcCount != stopPieces.Count ()) //if the piece count is the same already then no need to go through the loop
{
try
{
foreach (var item in stopPieces) //step through the items one at a time
{
int seek = mobilePcQuery.Where(s => s.unique_scan_code == item.item_detail.unique_scan_code select s.Id).FirstOrDefault ();
if (seek == 0) //if we do not already have the item create it
{
mobile_Item_Detail newItem = new mobile_Item_Detail ();
newItem.item_description = item.item_detail.item_description;
newItem.LOB_item_detail_id = item.item_detail.Id;
newItem.mobile_stops_id = mstopId;
newItem.dt_seq_no = item.item_detail.dt_item_seq_no;
newItem.unique_scan_code = item.item_detail.unique_scan_code;
mdbPcs.mobile_Item_Detail.Add (newItem);
}
}
mdbPcs.SaveChanges ();
} catch (Exception ex) {
if (ex.InnerException.InnerException.Message.Contains ("UNIQUE KEY")) //WTH -- Why does this keep happening...how do I fix this??!
{
Console.WriteLine ($"{DateTime.Now}Unique Contraint {message} {newItem.unique_scan_code} for stop {newItem.mobile_stops_id}");
//item was already created by another thread so continue the foreach loop (I guess?!)
continue;
}
throw;
}
}
}
让我知道这是否有帮助。