SaveChanges()不会使用更新的数据来修改现有数据库记录

时间:2019-02-13 21:20:36

标签: c# sql entity-framework

我试图通过调用_dbContext.SaveChanges()来更新SQL数据库中的现有记录,但是它没有使用我修改的新值来更新记录。

我尝试了所有其他解决方案,但都没有用。

我的代码如下:

public int UpdateRank(Guid localId, int rank, Guid entityTypeId)
{            
    var result = _dbContext.EntityAttribute.FirstOrDefault(en => en.ParentGuid == localId && en.EntityAttributeTypeId == entityTypeId);
        result.IntValue = rank;
        return _dbContext.SaveChanges();            
    }

找到一些解决方案后,我还尝试添加

_dbContext.Entry(result).State = EntityState.Modified;

以及

_dbContext.EntityAttribute.Attach(result);

在_dbContext.SaveChanges()之前无效。

如果我从_dbContext.SaveChanges()之前的这些代码片段中获取任何先前的代码序列,则代码将运行并且不会引发错误,但不会更新记录。如果我添加

_dbContext.EntityAttribute.Update(result);

然后调用SaveChanges,出现以下错误: SqlException:无法更新标识列“ ID”。

ID是数据库生成的bigint。我都加了

_dbContext.EntityAttribute.Update(result).Property(en => en.Id).IsModified = false;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]

分别访问我的数据访问项目中的UpdateRank方法和EntityAttribute数据库文件,它们使代码运行没有错误,但是在调用SaveChanges之后仍未更新记录。

当我调试代码时,我可以看到result上的IntValue属性每次检索时都输入我输入的第一个值(4),因此它看起来好像dbContext保留了结果对象。只是没有用修改后的值更新我的数据库。我的数据库也是一个远程数据库,它不在我的本地计算机上托管。我找不到任何说明可能是问题的东西。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您可能需要为问题添加更多详细信息,包括EntityAttribute的实体定义和/或EF实体类型配置,包括任何要映射的属性。是否将“ IntValue”作为FK映射到另一个实体?这是导致您看不到更新的最可能原因。

例如,如果EntityAttribute看起来像这样:

public class EntityAttribute
{
   // ... properties, key, etc.

   public int IntValue { get; set; }

   [ForeignKey("IntValue")]
   public virtual IntAttribute MyInt { get; set; }
}

然后您遇到一种情况,有两种方法可以将EntityAttribute指向一个新的IntAttribute实例,以及一些麻烦的解决方案。如果记录开始的IntValue为4且ID为4的MyInt,则暗示将其更改为“ 5”是因为将IntValue设置为5或将MyInt设置为ID = 5的实体。第二种选择是正确的您已经定义了FK列:

public int UpdateRank(Guid localId, int rank, Guid entityTypeId)
{            
    var result = _dbContext.EntityAttribute.Single(en => en.ParentGuid == localId 
        && en.EntityAttributeTypeId == entityTypeId);
    var myInt = _dbContext.MyInts.Single(x => x.MyIntId == rank);
    result.MyInt = myInt;
    return _dbContext.SaveChanges();            
}

这是假设FK指向带有名为MyInts的实体DbSet的引用属性“ MyInt”。在您的实体中为ID(PK和FK)采用正确的命名约定将大大有助于使您的代码更易于理解。

请注意,我将FirstOrDefault更改为Single。对于Linq,请使用限制性最高的预期操作。仅当您预期行应该可用或不可用并且正在处理不可用的情况时,才使用“ OrDefault”。如果期望1行,请使用“单”而不是“第一”。 “第一”表示我期望有很多,但只关心第一个,它应始终包含OrderBy子句。这是为了避免潜在的错误(更新错误的记录,以NullReference异常结束等)

现在,如果您确定没有FK参考,请尝试以下操作:

public int UpdateRank(Guid localId, int rank, Guid entityTypeId)
{            
    var result = _dbContext.EntityAttribute.Single(en => en.ParentGuid == localId 
         && en.EntityAttributeTypeId == entityTypeId);
    result.IntValue = rank;
    return _dbContext.SaveChanges();            

    var test = result.IntValue;
}

var test = ...行上放置一个断点。 返回到test的值是什么?如果原始IntValue为“ 4”,等级为“ 5”,并且test返回为“ 4”,那么肯定会出现奇怪的情况。如果test返回为“ 5”,则此时的数据库也应报告“ 5”,可能是其他原因正在重置该值。在SaveChanges之后的“ test =“行上使用断点,使用手动查询检查数据库。如果查询无法在启用该断点的情况下运行,则另一个怀疑可能是您正在一个打开的事务中运行,并且在此调用之后未提交该事务。一个打开的事务将阻止查询执行,直到Tx作用域完成。对于事务,默认操作是在未告知要提交的情况下回滚所有更改。如果它没有锁定,并且数据库显示“ 4”,但是test显示“ 5”,那么我会仔细检查以确保您使用的是Single而不是FirstOrDefault,因为看起来像一个错误,您正在查询数据库中的一条记录,但是EF选择了另一条记录。 (即,您期望有1条记录,但是有多个符合条件的记录。)在这种情况下,使用Single会引发异常,结果是期望有1条记录,但返回了多条记录。