【问题标题】:Database Won't Update Using Savechanges Method on Entity在实体上使用 Savechanges 方法不会更新数据库
【发布时间】:2013-07-19 15:36:22
【问题描述】:

我在 MVC Web API 中使用实体框架,但我无法弄清楚为什么没有将更改保存到数据库中。我正在使用以下代码:

[HttpPost]
public HttpResponseMessage PostPXE(PXE pxe)
{
    var pxeRequestID =
        from qsp in db.Queue_Server_Provision
            .Where(a => a.Server_Name == pxe.Server_Name)
        join isni in db.IaaS_Server_NIC_Information
            .Where(a => a.MAC == pxe.Mac_Address) 
        on qsp.IaaS_ID equals isni.IaaS_Server_Information_IaaS_ID
        select qsp.Request_ID;

    var QSP = db.Queue_Server_Provision.Find(pxeRequestID.FirstOrDefault());

    db.Queue_Server_Provision.Attach(QSP);
    QSP.Provision_Status_Code = "240.9";
    db.Entry(QSP).State = EntityState.Modified;

    try
    {
        db.SaveChanges();
    }
    catch (DbUpdateConcurrencyException e)
    {
        return Request.CreateResponse(HttpStatusCode.NotFound, e.Message);
    }
    catch (Exception e)
    {
        return Request.CreateResponse(HttpStatusCode.NotFound, "error");
    }

    return Request.CreateResponse(HttpStatusCode.OK);
}

虽然在我调用 SaveChanges() 方法之前调试一切似乎都可以正常工作,但此时 Provision_Status_Code 值会恢复为修改前的值。

以下 SQL 是从实体框架生成的:

exec sp_executesql
    N'update [dbo].[Queue_Server_Provision]
      set [Server_Name] = @0,
          [Environment_List_ID] = @1,
          [Operating_System_List_ID] = @2,
          [Container_Size_List_ID] = @3,
          [Active_Directory_List_ID] = @4
      where ([Request_ID] = @5)
      select [IaaS_ID],
             [Provision_Status_Code],
             [Provision_Status_Text],
             [Provision_Phase],
             [Last_Update_Time],
             [Canceled]
      from [dbo].[Queue_Server_Provision]
      where @@ROWCOUNT > 0 and [Request_ID] =  5',
    N'@0 nvarchar(16),
      @1 uniqueidentifier,
      @2 uniqueidentifier,
      @3 uniqueidentifier,
      @4 uniqueidentifier,
      @5 uniqueidentifier',
    @0=N'IaaSTest222',
    @1='31097372-E4A6-461D-AFCC-BFAF069A6710',
    @2='CF44FE08-56DE-4A7D-813A-08A7AD215E8B',
    @3='15AEB74F-E0CB-4219-AC69-8C623DE8DF46',
    @4='EA08BB7E-5C1F-4F6B-83D6-4BF9F6C55FF7',
    @5='34CA5F9C-2BF8-40E5-8BDD-5DE7364C18C3'

【问题讨论】:

  • 您遇到了什么错误?在哪里(在哪条线上)?
  • 我没有收到任何错误。一切都执行得很好。如果我将 db.SaveChanges(); 更改为 int rowsUpdated = db.SaveChanges(); rowsUpdated 的值为 1。
  • 上述代码执行成功后,数据库保持不变。
  • 如果在附加之前修改值会发生什么?我相信这可能是你的问题。
  • 你能不能把Attach... = EntityState.Modified这行都去掉后试试。它们不是必需的。但是,它们也应该无关紧要,但是谁知道...

标签: entity-framework entity


【解决方案1】:

这看起来很像实体框架“认为”Provision_Status_Text 列是在数据库中生成的——要么是因为它是一个标识(不太可能是字符串列),要么是因为它是一个计算列。

这方面的指示是:

  • 该列不是 set 语句中 set 表达式的一部分,尽管您更改了该列。如果该列是数据库生成的,这是预期的。

  • 该列在 sql select 表达式中返回。对于数据库生成的列,这也是预期的,因为 EF 希望在插入或更新后使用当前计算的数据库值更新客户端的实体。

这同样适用于select 语句中出现的其他列。

如果您使用的是 Code-First 工作流程,请检查这些属性是否带有注释

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]

属性或如果

....HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
....HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)

与 Fluent API 一起使用。

如果您在 EDMX 中使用 Database-First 或 Model-First 工作流程,请检查您的 EDMX 文件中的 StoreGeneratedPattern="Identity"StoreGeneratedPattern="Computed" 属性。您也应该在设计器界面中找到这些设置。

这并不一定意味着该列确实是在数据库中生成的。但是,如果这些设置之一在模型元数据中,EF 将假定它是并且按照您看到的方式运行。这可能意味着数据库和模型由于某种原因“不同步”,因为在数据库架构或模型中进行了一些手动更改,可能没有更新另一方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多