Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何避免在实体框架手动插入中重复主键?_C#_Sql Server_Entity Framework_Asp.net Web Api - Fatal编程技术网

C# 如何避免在实体框架手动插入中重复主键?

C# 如何避免在实体框架手动插入中重复主键?,c#,sql-server,entity-framework,asp.net-web-api,C#,Sql Server,Entity Framework,Asp.net Web Api,通常在过去,在使用实体框架之前,我们对每个表使用复合键,并手动迭代键。举个简单的例子,本例中的父表基本上是vendor和log type,其fk是log表的主键 +--------------+-------------+ | VendorID(PK) | Name | +--------------+-------------+ | 1 | ABC Company | | 2 | XYZ Company | +-------------

通常在过去,在使用实体框架之前,我们对每个表使用复合键,并手动迭代键。举个简单的例子,本例中的父表基本上是vendor和log type,其fk是log表的主键

+--------------+-------------+
| VendorID(PK) |    Name     |
+--------------+-------------+
|            1 | ABC Company |
|            2 | XYZ Company |
+--------------+-------------+

+---------------+---------------+------------+
| idVendor(PK ) | LogTypeID(PK) |    Name    |
+---------------+---------------+------------+
|             1 |             1 | Info       |
|             1 |             2 | Warning    |
|             1 |             3 | Error      |
|             2 |             1 | Notice     |
|             2 |             2 | Warning    |
|             2 |             3 | Alert      |
|             2 |             4 | Audit      |
|             2 |             5 | Restricted |
+---------------+---------------+------------+

    +--------------+---------------+-----------+--------------------------------------+
    | idVendor(PK) | idLogType(PK) | LogID(PK) |               Message                |
    +--------------+---------------+-----------+--------------------------------------+
    |            1 |             1 |         1 | Notice of event that happened        |
    |            1 |             1 |         2 | Another notice from a different user |
    |            1 |             3 |         1 | An error from an upload              |
    |            1 |             1 |         3 | Notice of user                       |
    |            1 |             3 |         2 | An error from delete                 |
    +--------------+---------------+-----------+--------------------------------------+
因此,基本上在存储过程中,我们只需获得活动日志的max id+1,其中vendor=abc company,log=info。我们更喜欢使用复合键来增强数据一致性,并且我们喜欢使用尽可能最小的数据类型,而不是到处使用任意整数和大整数。例如,日志类型表我不需要对日志类型id使用小int,因为一个供应商的日志类型永远不会超过255个,所以对于每个供应商,我们在那里设置了自定义日志类型,并将日志类型id重新启动为1

好的,现在来回答问题。。 在手动迭代LogID时使用实体框架,有时会在insert for QA(更多的测试活动)上出现重复的主键错误。我们有一个新的AngularJS应用程序,它向我们发送insert请求,但当有多个insert时,我猜在实际插入记录之前,所有3个insert都会立即执行max函数+1。发生这种情况时,它会尝试为三个插入插入相同的LogID。如何在不影响我们多年来一直行之有效的数据库设计的情况下阻止这种情况的发生

下面是插入的示例代码。为了简化问题,我省略了不必要的列:

public IHttpActionResult InsertLog(JobOrderNote.InsertUpdate Log)
{
    using (dbContext db = new dbContext())
    {
        tbl_ActivityLog insLog = new tbl_ActivityLog()
        {
            LogEntry = Log.LogEntry,
            idVendor = Log.VendorID,
            idLogType = Log.LogTypeID,
            LogID = (db.tbl_ActivityLog
                            .Where(log =>
                                log.idVendor == log.VendorID &&
                                log.idLogType == log.LogTypeID)
                            .DefaultIfEmpty()
                            .Max(id => id == null ? 0 : id.LogID)) + 1,
        };

        db.tbl_ActivityLog.Add(insLog);
        return Ok();
    }
}

手动生成的ID被认为是一种糟糕的数据库做法。使用什么工具集并不重要。使用数据库生成的自动递增ID


如果必须使用组合键保持表结构不变,那么我建议创建一个存储过程,增加ID号并向您返回一个新的ID号。因此,您需要创建一个表来管理ID。因此,对于每个供应商和日志类型,它需要跟踪消息表使用的下一个ID号。它将预先增加该数字,然后返回该数字。您需要将事务隔离级别设置为serializable,以便对存储过程的两个同时调用将产生唯一的值。

sigs-这太糟糕了。我认为在过去的十年中,我们一直在使用存储过程,所以从未遇到实体框架的这种限制。仅从数据库的角度来看,对于只需要一个字节(255)的数据,使用一个可能超过20亿的整数是没有意义的,这就是为什么我们不使用自动递增键的原因。我不知道这是否是一个坏习惯,因为键的约束不允许重复,所以完整性仍然存在。也许我会使用一些缓存方法来保存迭代数据(idk)。这种情况也可能发生在存储过程中,具体取决于事务隔离级别。这可能只是因为它发生在DB中,所以不太可能发生。听起来你正在做很多工作,试图在这些键上保存一些字节。考虑一下基准测试,看看这是否真的是必要的。相反,我正在努力节省数周甚至几个月的工作量。较旧的系统使用该数据库时没有出现重复的pk错误(如您所说,在db中,它必须更快地完成处理,因此我们从未收到错误)。我们正在将该系统转换为Angular\Web API应用程序。所以我试图避免重新定义数百个表lol。也许我可以用powershell脚本将所有PK转换成AK,然后将单列标识PK替换掉。这应该是一个有趣的项目,我决定对PK使用任意自动递增键,并将复合键移到备用键中,以保持数据完整性。感谢您的反馈,Moby