这有点复杂,拜托,我知道所有反对自然 PK 的论点,所以我们不需要讨论。
使用 VS2012/MVC4/C#/CodeFirst
因此,PK 是基于日期和相应的数字。因此,今天创建的几行将是这样的:
20131019 1
20131019 2
明天创造一个:
20131020 1
这必须使用 C# 或作为触发器或其他方式自动生成。用户不会输入这个。我确实想出了一个解决方案,但是我遇到了问题,而且我有点卡住了,因此提出了这个问题。
所以,我有一个模型:
public class MainOne
{
//[Key]
//public int ID { get; set; }
[Key][Column(Order=1)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string DocketDate { get; set; }
[Key][Column(Order=2)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string DocketNumber { get; set; }
[StringLength(3, ErrorMessage = "Corp Code must be three letters")]
public string CorpCode { get; set; }
[StringLength(4, ErrorMessage = "Corp Code must be four letters")]
public string DocketStatus { get; set; }
}
完成模型后,我使用 VS2012 脚手架创建了一个新的控制器和视图。
然后,我正在做的是调试以创建数据库,然后在 Code First 创建数据库之后添加以下内容而不是触发器 [我不知道这是否是正确的过程]:
CREATE TRIGGER AutoIncrement_Trigger ON [dbo].[MainOnes]
instead OF INSERT AS
BEGIN
DECLARE @number INT
SELECT @number=COUNT(*) FROM [dbo].[MainOnes] WHERE [DocketDate] = CONVERT(DATE, GETDATE())
INSERT INTO [dbo].[MainOnes] (DocketDate,DocketNumber,CorpCode,DocketStatus) SELECT (CONVERT(DATE, GETDATE
())),(@number+1),inserted.CorpCode,inserted.DocketStatus FROM inserted
END
当我尝试创建记录时,这是我得到的错误:
对数据库的更改已成功提交,但在更新对象上下文时出错。ObjectContext 可能处于不一致的状态。内部异常消息:无法更改对象状态。此异常可能是由于将一个或多个主键属性设置为 null 造成的。未添加的对象不能有空的主键值。有关详细信息,请参阅内部异常。
现在,对我来说有趣的是,在我停止调试并重新开始之后,一切都很完美。触发器完美触发,所以复合PK唯一完美,其他列数据完好。
我的猜测是,在给出插入命令之前,PK 似乎没有任何价值,这让 EF 感到困惑。此外,似乎支持这一理论的是,当我尝试编辑行时,在调试中,我收到以下错误:
传递的主键值的数量必须与实体上定义的主键值的数量相匹配。
如果我尝试提取“详细信息”或“删除”功能,则会出现同样的错误。
关于如何解决这个问题的任何解决方案或想法?我对任何事情都很开放,甚至创建一个隐藏的 int PK。但这似乎是多余的。
编辑 21OCT13
[HttpPost]
public ActionResult Create(MainOne mainone)
{
if (ModelState.IsValid)
{
var countId = db.MainOnes.Count(d => d.DocketDate == mainone.DocketNumber); //assuming that the date field already has a value
mainone.DocketNumber = countId + 1; //Cannot implicitly convert type int to string
db.MainOnes.Add(mainone);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(mainone);
}
编辑 21OCT2013 最终代码解决方案 对于像我这样不断寻找清晰和完整解决方案的人。
if (ModelState.IsValid)
{
String udate = DateTime.UtcNow.ToString("yyyy-MM-dd");
mainone.DocketDate = udate;
var ddate = db.MainOnes.Count(d => d.DocketDate == mainone.DocketDate); //assuming that the date field already has a value
mainone.DocketNumber = ddate + 1;
db.MainOnes.Add(mainone);
db.SaveChanges();
return RedirectToAction("Index");
}