【问题标题】:Get the last ID in Entity Framework table so new record can be set as LastID+1?获取实体框架表中的最后一个 ID,以便可以将新记录设置为 LastID+1?
【发布时间】:2015-04-03 05:35:48
【问题描述】:

我将实体框架与 Oracle 数据库一起用于 MVC5 应用程序。对于我创建新的Vendor 实体的控制器操作,我有以下内容:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Create([Bind(Include = "Id,vendor_name,created_date,created_by,modified_date,modified_by")] INV_VENDORS iNV_Vendors)
    {
        if (!db.INV_VENDORS.Any(m => m.VENDOR_NAME == iNV_Vendors.VENDOR_NAME))
        {
            //decimal id = db.INV_VENDORS.Last().ID + 1;
            //iNV_Vendors.ID = db.INV_VENDORS.Last().ID + 1;
            iNV_Vendors.CREATED_DATE = DateTime.Now;
            iNV_Vendors.CREATED_BY = System.Environment.UserName;

            ModelState.Clear();
            TryValidateModel(iNV_Vendors);

            if (ModelState.IsValid)
            {

                db.INV_VENDORS.Add(iNV_Vendors);
                await db.SaveChangesAsync();
                return RedirectToAction("Index");


            }
        }
        else
        {
            ModelState.AddModelError("vendor_name", "The Vendor [" + iNV_Vendors.VENDOR_NAME + "] already exists in the table.");
        }
        return View(iNV_Vendors);
    }

当我加载视图并输入一个值(例如,"TEST")时,代码从断点一直执行到await db.SaveChangesAsync();,并在此引发错误Oracle.ManagedDataAccess.Client.OracleException ORA-00001: unique constraint (INVENTORY.PK_INV_VENDORS) violated ORA-06512

我不太清楚为什么会出现此错误,因为数据库有一个触发器,每次有新的 INSERT 时都会自动增加 ID 字段值:

CREATE OR REPLACE TRIGGER INV_VENDORS_TRG
BEFORE INSERT
ON INVENTORY.INV_VENDORS
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
-- For Toad:  Highlight column ID
  :new.ID := INV_VENDORS_SEQ.nextval;
END INV_VENDORS_TRG;
/

在我的DAL 文件夹的INV_VENDORS 类中,我尝试为ID 字段指定[DatabaseGenerated] 选项,但在尝试创建新的VENDOR 实体时仍然收到相同的错误:

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public decimal ID { get; set; }

通过测试,似乎 Entity Framework 将我的控制器代码中的 iNV_Vendors.ID 值自动设置为 0,这导致了重复错误——该表目前已经包含 ID 1-23 的值。

有谁知道如何通过 linq 在数据库中查询表中的最后一个 ID 值,以便我可以将 iNV_Vendors.ID 指定为返回值 + 1? (或者如果这是一个坏主意,也许是正确的方法?)

【问题讨论】:

  • 实体框架未将值设置为 0。Decimal 是一种值类型,因此默认为 0。
  • 我明白了。我仍然不确定为什么该字段甚至被定义为Decimal。我使用 Entity Framework Designer 选择我的表并自动生成 DAL 类,这使得 int ID 字段在类中出现为 decimal
  • 您确定ID 是您唯一的PK,即不是与vendor_name 的复合键?
  • 等等,您提到使用设计器来创建您的类...这是代码优先还是数据库优先?我认为您不能将DatabaseGenerated 属性与数据库优先使用...您必须执行以下操作:stackoverflow.com/questions/7351260/…

标签: c# asp.net-mvc oracle linq entity-framework


【解决方案1】:

通过 EF 获取最后一个 id 并手动设置它是一个非常糟糕的主意,因为它肯定会在并发请求上失败。

由于 Oracle 不支持自动增量,您应该使用 thread 中提到的触发器解决方法(它实际上与您当前的实现有点不同)。

您是否在没有指定 Id 列值的情况下直接在数据库中测试插入?

【讨论】:

  • 我已经测试了手动插入数据库,并确认在使用 TOAD for Oracle 时不需要指定 ID 列值。我查看了您的链接,但与我已有的触发器相比,我不太明白有什么不同?
  • 是的,我的错,它们是一样的。您是否尝试过分析 EF 产生的实际查询?
  • 我不确定实际的查询,但在 await db.SaveChangesAsync() 之前添加的 iNV_Vendors 具有以下内容:CREATED_BY: {Me} | CREATED_DATE: {4/3/2015 8:43:57 AM} | ID: 0 | MODIFIED_BY: null | MODIFIED_DATE: null | VENDOR_NAME: "TEST"?
  • 看起来不错。使用分析器检查实际查询,这将有很大帮助。
  • 什么是/如何使用 Profiler?
猜你喜欢
  • 1970-01-01
  • 2013-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 2017-08-08
  • 2020-01-04
相关资源
最近更新 更多