azure web 作业因唯一约束而失败 - 假设由于其他线程

azure web job fails on unique constraint - assuming due to other thread

我有代码检查记录是否存在,如果不存在则插入它。 问题是它有时会失败。 它正在从消息队列中拉取。 我已经做了我能想到的一切,但它以某种方式在另一个'thread'(我假设)上创建记录在它检查之后和创建新记录之前的某个时间。

错误出现在 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;
                    }
                }
            }
        }

我假设 mobile_Item_Detail 有一个 Id 属性 表示身份 PK,mstopid 是与父项的 FK 关系。在那种情况下,我将对实体集合进行所有更改,然后在 foreach 外部调用保存更改。这样,DbContext 可以一次处理所有 ID,因为它通过 ChangeTracker 了解所有更改,并且可以在单个数据库调用中执行保存。您还可以将操作包装在事务中,以便在发生错误时轻松回滚更改。我还将操作包含在 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;
        }
    }
}

如果有帮助请告诉我。