sql-server - 创建新记录之前如何获取最大ID值?

标签 sql-server asp.net-mvc entity-framework primary-key code-first

我认为在很多情况下这是一个普遍问题,但我在网上没有找到正确的答案。在我的 MVC 应用程序中,我有下表:

问题表:

---------------------------------------------
IssueID (pk) | CategoryID (fk) | IssueNumber
---------------------------------------------
   1         |     1           |      1
   2         |     1           |      2
   3         |     2           |      1
   4         |     1           |      3


类别表:

-----------------------------------
CategoryID (pk) | Prefix | Name
-----------------------------------
     1          |   COM  | Computer
     2          |   GEN  | General


在这里,我对两个类别(COM 和 GEN)使用 IssueID(主键)字段。另一方面,我想依次生成 IssueNumber(1、2、3 ...),没有任何类别 ID 的间隙。另一方面,我还想从 1 为另一个类别创建 IssueNumber,如上所示。所以问题是:

1)上述方法有什么问题吗?如果是这样,您对此有何建议?

2) 创建记录之前如何获取 IssueNumber 的最大值?我想在 SaveChanges() 方法上进行此操作(我使用 Entity Framework )。由于我没有将 IssueNumber 字段设置为 PK,因此我无法使 MsSQL Server 自动递增该列值。

如有任何帮助,我们将不胜感激。提前致谢。


更新:

这是使用 lambda 的解决方案:

public int SaveIssue(Issue issue)
{
    int max = context.Issues.Where(m => m.CategoryID == issue.CategoryID ).Max(m => m.IssueNumber); 
    issue.IssueNum = max + 1; 

    context.Issues.Add(issue);
    context.SaveChanges(); 
    return issue.IssueNum ;
}

最佳答案

我不确定如何在 EF 中执行此操作,但可以通过 SQL 通过以下方式完成此操作(我假设 IssueID 是一个标识列)

CREATE PROCEDURE usp_CreateNewIssue
    @catagoryId int,
    @issueId int OUTPUT,
    @issueNumber int OUTPUT
AS
BEGIN
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    BEGIN TRANSACTION
        declare @maxId int        
        declare @newRow table (IssueID int NOT NULL, IssueNumber int NOT NULL)

        select @maxId = MAX(IssueNumber) from Issue where CategoryID = @catagoryId

        Insert Into Issue (CategoryID, IssueNumber) values (@catagoryId, @maxId + 1)
           OUTPUT INSERTED.IssueID, INSERTED.IssueNumber 
           INTO @newRow

        select @issueId = IssueID, @issueNumber = IssueNumber from @newRow
    COMMIT TRANSACTION
END

(在浏览器中编写的代码,未测试语法错误)

使用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE确保您阅读 MAX(IssueNumber) 后在您提交事务之前,其他查询都无法修改该结果。

注意:要获得良好的性能,请确保 CategoryID索引于Issue因此 SQL 引擎可以执行 Key-Range lock它而不是表锁。

关于sql-server - 创建新记录之前如何获取最大ID值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30077072/

相关文章:

php - 如果最近插入了日期,如何恢复正确的日期

c# - 如何在我的在线站点中引入在线数据库

jquery - 如何将 Html.Action 附加到 jquery

jquery - 在mvc中实现部分 View 分页的最佳方式

c# - mvc c# 文件上传为字节数组

c# - CompiledQuery.Compile 需要锁(EF4、SQL Server、C#)

sql-server - 如何从#temp 表生成插入数据脚本?

sql-server - 'multi-level' CTE 中的多部分标识符无法绑定(bind)错误

linq - 将iQueryable转换为IEnumerable

c# - 找不到 ASP.NET Core 2 MySQL 8.0.8-dmr Entity Framework 扩展