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

时间:2015-05-06 12:42:02

标签: 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 ......)而没有任何CategoryID的差距。另一方面,我还想从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 ;
}

1 个答案:

答案 0 :(得分:5)

我不确定如何在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而不是表锁。