为了账号安全,请及时绑定邮箱和手机立即绑定

避免重复插入数据库

避免重复插入数据库

C#
叮当猫咪 2022-11-22 15:36:15

我有以下代码插入一个具有随机生成值“hawb”的实体作为列之一。我的想法是,因为hawb是表中的唯一列,所以 try-catch 块将在插入重复值时捕获异常。工作流程工作正常,直到我开始测试它并出现一些奇怪的错误。


[Code]

hawb = "0402135505536";

while (!uniqueHawb)  //insert new hawb

{

    //hawb = $"{DateTime.Now:MMddHHmmss}{RandomHelper.GetRandomNumber(0, 999):000}";


    var entity = new HawbAsset { HAWB = hawb, HawbStatus = "Allocated", AllocatedDateTime = DateTime.Now, AllocationReference = reference };


    try

    {

        _repository.Insert(entity);

        uniqueHawb = true;

    }

    catch (Exception e)

    {

        ;

    }

    hawb = $"{DateTime.Now:MMddHHmmss}{RandomHelper.GetRandomNumber(0, 999):000}";

}


[Model]

    public class HawbAsset : BaseEntity

    {

        [Required(AllowEmptyStrings = false)]

        [Index(IsUnique = true)]

        [StringLength(15)]

        public string HAWB { get; set; }


        [Required(AllowEmptyStrings = false)]

        public string HawbStatus { get; set; }


        public DateTime? AllocatedDateTime { get; set; }


        [Required(AllowEmptyStrings = false)]

        public string AllocationReference { get; set; }


        public DateTime? ConfirmedUsageDateTime { get; set; }


        public DateTime? RecycledDateTime { get; set; }


        public string Owner { get; set; }

    }

我硬编码了一个重复值 0402135505536,因此它会在第一时间捕获“重复键异常”,这是预期的。然而,当 hawb 是随机生成的,并且我已经确定值不同时,它仍然会捕获相同的“Duplicate Key Exception”。谁能告诉我发生了什么以及如何实现我的目标?谢谢!


查看完整描述

3 回答

?
慕斯王

TA贡献1568条经验 获得超2个赞

您看到的问题是因为您尝试插入一个具有重复 ID 的实体但失败了。重试时,您正在创建第二个实体并尝试插入它。第一个实体仍与上下文相关联,并且仍将尝试保存。在保存新替换或更新现有实体之前,您需要将其与上下文分离。(以下)


hawb = "0402135505536";

var entity = new HawbAsset { HAWB = hawb, HawbStatus = "Allocated", AllocatedDateTime = DateTime.Now, AllocationReference = reference };

while (!uniqueHawb)  //insert new hawb

{

    //hawb = $"{DateTime.Now:MMddHHmmss}{RandomHelper.GetRandomNumber(0, 999):000}";


    try

    {

        _repository.Insert(entity);

        uniqueHawb = true;

    }

    catch (Exception e)

    {

        ;

    }

    entity.HAWB = $"{DateTime.Now:MMddHHmmss}{RandomHelper.GetRandomNumber(0, 999):000}";

}

要分离您需要使用的实体,context.Entity(entity).State = EntityState.Detached; 它需要通过您的存储库边界进行操作。


理想情况下,最好在尝试插入之前检查 HAWB 的唯一性,但仍然处理那些非常非常罕见的情况,即在检查和保存之间保存条目:


int retryCount = 0

while (retryCount < 5)

{

  try

  {

    bool isUnique = false;

    string hawb = null;

    while(!isUnique)

    { 

      hawb = generateHawb();

      isUnique = context.HawbAssets.Any(x => x.HAWB == hawb);

    }

    entity.HAWB = hawb; // this hawb should be unique, so set and insert.

    _repository.Insert(entity);

  }

  catch(UpdateException)

  {

  // log that this has happened, check inner exception for duplicate key and retry, though limit retry attempts if there are deeper issues that might lock up the system in a retry loop.

    retryCount++;

  }

}


查看完整回答
反对 回复 2022-11-22
?
PIPIONE

TA贡献1541条经验 获得超1个赞

它的 1 行额外代码用于检查实体是否存在。先做这件事,不要依赖错误处理来完成工作:


if ( _repository.HAWBAssets.FirstOrDefault(i => i.HAWB == hawb)== null)

    {

     _repository.Insert(entity);

        uniqueHawb = true;

    }


查看完整回答
反对 回复 2022-11-22
?
白衣染霜花

TA贡献1526条经验 获得超9个赞

也许您可以使用纳秒来使记录之间的距离变大,以减少重复的可能性


entity.HAWB = $"{DateTime.Now.Ticks}";

// 636898603227146583

DateTime.Ticks分辨率为 100 纳秒


查看完整回答
反对 回复 2022-11-22
  • 3 回答
  • 0 关注
  • 12 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信