Jac*_*ack 2 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
Run Code Online (Sandbox Code Playgroud)
分类表:
-----------------------------------
CategoryID (pk) | Prefix | Name
-----------------------------------
1 | COM | Computer
2 | GEN | General
Run Code Online (Sandbox Code Playgroud)
在这里,我对两个类别(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 ;
}
Run Code Online (Sandbox Code Playgroud)
我不知道如何在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
Run Code Online (Sandbox Code Playgroud)
(用浏览器编写的代码,因语法错误未经测试)
使用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE确保在您读取之后MAX(IssueNumber)没有其他查询可以修改该结果,直到您提交事务为止.
注意:为了获得良好的性能,请确保CategoryID已编入索引,Issue以便SQL引擎可以对其执行键范围锁定而不是表锁定.
| 归档时间: |
|
| 查看次数: |
1531 次 |
| 最近记录: |