[asp.net-mvc]实体框架︰ 处理主唯一键值 (标识规范关闭) 为新记录

发布时间: 2017/3/25 9:23:32
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

首先,我不能修改表的设计,若要打开主键标识规范。

我的问题是如何处理在 EF 用户 A 和用户 B 将有没有冲突主键中添加新记录时。

我正在对 Asp.Net MVC5 项目。

我当前的代码︰

public void NewFooMember(FooMember fooMember)
{
    fooMember.NullGuard("fooMember");
    // This is the primary key
    fooMember.MemberKey = NextFooMemberKey();
    Repo.Add(fooMember);
    UnitOfWork.Commit();
}

public int NextFooMemberKey()
{
    int? maxFooMemberKey = Repo.Data.Max(fm => (int?)fm.MemberKey);
    if (!maxFooMemberKey.HasValue)
    {
        return 1;
    }
    return maxFooMemberKey.Value + 1;
}

解决方法 1:

你当前的想法有两个不同的调用可对缺陷 NextFooMemberKey 同时,要么插入新的记录之前,导致在两个记录被插入到数据库使用相同的密钥。

为了解决这个问题,你应该确保线程安全的让这个序列并添加 lock 的电话围绕关键的生成和插入功能,确保只有一个线程可以运行那部分代码 (确保唯一键) 一次。

你也可以与一些优化键生成函数-假设你不能处理多个服务器,你可以缓存最后一把钥匙和只递增它每次-这种方式,你可以不去到数据库您正在生成密钥 (您将需要解决在哪里插入失败的场景每次往返在这种情况下你需要减少你静态保存的键)。

private object newFooLock = new object();

public void NewFooMember(FooMember fooMember)
{
  fooMember.NullGuard("fooMember");
  lock (newFooLock) {        // now only one thread can get in here at a time
    try 
    {
      fooMember.MemberKey = NextFooMemberKey();
      Repo.Add(fooMember);
      UnitOfWork.Commit();
    }
    catch (Exception ex)
    {
      lastFooKey--;    // decrement saved value
    }
  }
}

private object newFooKeyLock = new object();
private static int? lastFooKey = null;

public int NextFooMemberKey()
{ 
  // also lock the key generation, just to be safe
  lock (newFooKeyLock) { 
    if (lastFooKey == null) 
    {
      // only get from the db if the local value is not yet populated
      lastFooKey = Repo.Data.Max(fm => (int?)fm.MemberKey) ?? 1;
    }
    lastFooKey++;
    return lastFooKey.Value;
  }
}
赞助商