1

这有点复杂,拜托,我知道所有反对自然 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");
        }
4

1 回答 1

1

你为什么不通过代码而不是使用触发器来管理它?

var countId = context.MainOne.Count(d => d.DocketDate == newItem.DocketNumber); //assuming that the date field already has a value
newItem.DocketNumber = CountId + 1;
Context.MainOne.Add(newItem);
context.SaveChanges();

这应该可以解决您的问题。

于 2013-10-21T06:06:21.493 回答