我试图通过调用_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后,记录仍未更新。
当我调试代码时,我可以看到结果上的IntValue属性在每次检索时都有我输入的第一个值(4),因此看起来好像dbContext保留在结果对象上。它只是没有用修改后的值更新我的数据库。我的数据库也是一个远程数据库,它不在我的本地计算机上托管。我无法找到任何可能存在问题的内容。
任何帮助,将不胜感激。
您可能需要在问题中添加更多详细信息,包括EntityAttribute
的实体定义和/或EF实体类型配置,包括映射的任何属性。 “IntValue”是否被映射为另一个实体的FK?这是您没有看到更新的最可能原因。
例如,如果EntityAttribute看起来像:
public class EntityAttribute
{
// ... properties, key, etc.
public int IntValue { get; set; }
[ForeignKey("IntValue")]
public virtual IntAttribute MyInt { get; set; }
}
然后你会遇到这样一种情况:有两种方法可以在新的IntAttribute实例中指向EntityAttribute,还有一些鸡蛋和鸡蛋情景。如果记录的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指向名为“MyInt”的引用属性,其中包含名为MyInts的实体DbSet。在您的实体中为ID(PK和FK)采用适当的命名约定将使您的代码更容易理解。
注意我将FirstOrDefault
改为Single
。使用Linq,使用最严格的预期操作。如果您希望行可用或不可用,则仅使用“OrDefault”,并且正在处理它们不可用的情况。如果您期望1行,请使用“单个”而不是“第一个”。 “第一”表示我期待很多,但只关心第一个,它应该总是包括一个OrderBy
条款。这是为了避免潜在的错误(更新错误的记录,最后是NullReference Exceptions等)
现在,如果您确定没有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”,则rank为“5”,test
返回为“4”,然后奇怪的是肯定会发生。如果test
返回为“5”,那么此时的数据库也应报告“5”,并且可能还有其他东西正在重置该值。使用SaveChanges之后的“test =”行上的断点,使用手动查询检查数据库。如果查询无法在启用该断点的情况下运行,则另一个嫌疑人将是您在打开的事务中运行,并且在此调用之后未提交事务。打开事务将阻止查询执行,直到Tx范围完成。对于事务,默认操作是回滚任何更改,如果它没有被告知提交。如果它没有锁定并且DB显示“4”但是test
显示“5”那么我会仔细观察以确保你使用Single
而不是FirstOrDefault
,因为这看起来像你查询一条记录的错误在数据库中,但EF正在选择另一个。 (即你期望有1条记录,但有多条符合标准。)在这种情况下使用Single
会引发一个异常,即预期有1条记录,但多条返回。