如何避免实体框架手册中的主键重复插入

本文关键字:插入 实体 何避免 框架 | 更新日期: 2023-09-27 18:23:56

通常在过去使用实体框架之前,我们对每个表都使用复合键,并手动迭代键。举个简单的例子,在这种情况下,基本上父表是供应商和日志类型,其fk是日志表的pk

+--------------+-------------+
| 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                 |
    +--------------+---------------+-----------+--------------------------------------+

因此,基本上在存储过程中,我们只会得到活动日志的最大id+1,其中vendor=abc company,log=info。我们更喜欢使用复合键来增强数据一致性,并且我们喜欢使用尽可能小的数据类型,而不是到处使用任意的int和大int。例如,在日志类型表中,我不需要为日志类型id使用小int,因为供应商的日志类型永远不会超过255个,所以我们为每个供应商设置了自定义日志类型,并将日志类型id重新启动为1。

好了,现在问题来了

当我手动迭代LogID时,使用实体框架,我有时会在插入QA时遇到重复的主键错误(更多的测试活动)。我们有一个新的AngularJS应用程序,它向我们发送插入请求,但当有多个插入时,我想在记录的任何实际插入之前,所有3个插入都会立即发生最大函数+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号。它将预先递增该数字,然后返回该数字。您需要将事务隔离级别设置为可序列化,以便对存储过程同时进行两次调用将产生唯一的值。