如何使用Entity Framework 6更新记录?

11 浏览
0 Comments

如何使用Entity Framework 6更新记录?

我正在尝试使用EF6更新一条记录。首先查找记录,如果存在,则进行更新。\n以下是我的代码:\n

var book = new Model.Book
{
    BookNumber =  _book.BookNumber,
    BookName = _book.BookName,
    BookTitle = _book.BookTitle,
};
using (var db = new MyContextDB())
{
    var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber);
    if (result != null)
    {
        try
        {
            db.Books.Attach(book);
            db.Entry(book).State = EntityState.Modified;
            db.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}

\n每次我尝试使用以上代码更新记录时,都会出现以下错误:\n

{System.Data.Entity.Infrastructure.DbUpdateConcurrencyException: 存储更新、插入或删除语句影响了意外数量的行(0)。实体可能已在加载实体后被修改或删除。请刷新ObjectStateManager条目。

0
0 Comments

如何使用Entity Framework 6更新记录?

问题出现的原因是AddOrUpdate()方法在数据库迁移期间使用,强烈建议不要在迁移之外使用该方法,这也是为什么它在Entity.Migrations命名空间中的原因。

解决方法是,如果需要更新现有行,不要使用AddOrUpdate()方法。如果没有使用搜索引用(例如ID)的书籍,它将创建新行,这在某些情况下可能会成为问题(例如,如果您尝试为不存在的行调用PUT方法,它将返回404-未找到的响应)。

不要使用此方法,除非您知道自己在做什么!请阅读:michaelgmccarthy.com/2016/08/24/...

可以提醒大家,对于所需的用例,这不是一个好的解决方法。

0
0 Comments

如何使用Entity Framework 6更新记录?

在我检查Entity Framework的源代码时,我发现了一种方法,可以根据Key属性更新实体:

public void Update(T item) where T: Entity
{
    // 假设Entity基类为所有项提供了一个Id属性
    var entity = _collection.Find(item.Id);
    if (entity == null)
    {
        return;
    }
    _context.Entry(entity).CurrentValues.SetValues(item);
}

否则,请检查AddOrUpdate的实现以获取想法。

希望这对你有所帮助!

不错!不需要枚举所有属性。我假设需要在设置值后调用SaveChanges()

是的,更改将在SaveChanges()时持久化。

很棒的答案,通过智能感知并不太明显,像这样的操作是行不通的:_context.MyObj = newObj; 然后 SaveChanges() 或者.... _context.MyObj.Update(newObj) 然后 SaveChanges(); 你的解决方案可以更新整个对象,而无需循环遍历所有属性。

这会告诉我正在尝试编辑ID字段。

运行此代码需要哪些引用?我遇到了以下错误:T does not contain a definition for Id _collection does not exist in the current context

T是一个泛型参数,使用你的实体类代替:User,Order,...

- 如果模型之间的ID字段(或者你将主键定义为其他内容)不同(包括一个模型中的null / 0),就会出现这个错误。确保两个模型之间的ID匹配,它将正常更新。

哇,改变生活了。在设置值之前,我必须执行以下操作以保持主键相同... entity.Id = existingEntity.Id;

- 你能在这里更新你的答案,加入关于ID的注释吗?在阅读它们之前,我被绊倒了一段时间。

这里的_collection是什么?

_collection变量是一个DbSet

此代码试图更新所有值,而不考虑空条目。如果未提供新值,我希望旧对象中的值保持不变!任何帮助将不胜感激。

我没有做你建议的事情,但是这个方法的整个思想是你有一个有效的实体要更新。如果你传递的实体有一些在数据库中不为空的空属性,你就会不同步或在代码中显式将属性设置为null。

请提供一种更好的方法来在EF边界内检索当前实体。如果您的实体不在内存中,这将触发一个查询。大多数时间它会在内存中或者您会在之后重用。无论如何,这个查询将在关键字上有一个where子句(这是索引的),我可以想到一种更快的方法来在那个时候检索数据库的值。你认为这是业余的,它很好,请给我们以真理的启示。

对于我来说,这会在倒数第二行抛出一个Member 'CurrentValues' cannot be called for the entity of type 'Entity' because the entity does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet.错误

你修改了查询行(var entity = _collection.Find(item.Id);)还是实体已经不存在了?这是一个用于更新现有实体的更新方法。

0
0 Comments

使用Entity Framework 6更新记录的方法

你正在尝试更新记录(对我来说意味着“更改现有记录的值并保存”)。所以你需要检索对象,进行更改,然后保存。

using (var db = new MyContextDB())
{
    var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber);
    if (result != null)
    {
        result.SomeValue = "Some new value";
        db.SaveChanges();
    }
}

那么这个方法到底是如何工作的呢?将一个值赋给"result"并不会直接更新数据库,而是调用db.SaveChanges()来更新上下文中的修改对象才会更新数据库。

仍然令我着迷...所以var result实际上与dbcontext相关联...这意味着任何由任何dbcontext成员实例化的变量都将与数据库相关联,因此对该变量所做的任何更改也将应用或持久化?

因为上下文生成了对象,所以上下文可以跟踪对象,包括对对象的更改。当你调用SaveChanges时,上下文会评估它所跟踪的所有对象,以确定它们是添加、更改还是删除,并针对连接的数据库发出适当的SQL语句。

我正在遇到相同的问题-使用EF6,尝试更新实体。Attach + EntityState.Modified不起作用。唯一起作用的是-你需要检索对象,进行所需的更改,并通过db.SaveChanges()保存它。

这个查询是一样的吗?var result = db.Books.Where(b => b.BookNumber == bookNumber).SingleOrDefault();是否有任何性能上的考虑在FirstOrDefaultSingleOrDefault之间?

是的,这个查询是相同的,因为它会返回相同的结果。你需要测试一下,在你具体的情况下是否有性能差异。

你不应该必须先检索对象才能更新它。我遇到了同样的问题,直到我意识到我试图更改主键值之一(复合主键)。只要提供正确的主键,你可以将EntityState设置为Modified,然后SaveChanges()就会起作用,前提是你没有违反表上定义的其他完整性约束。

我正在做类似的事情,但是不是更新,而是为我添加了一个新的条目。有什么想法为什么会这样?

这是因为结果是按引用传递的,所以这样可以工作。

当你使用第3行获取项目时,它会自动设置为更改跟踪。这就是为什么这个方法可以工作的原因。如果要采用另一种方式,你需要不加载更改跟踪(省略第3行),然后附加,设置状态为Modified,然后保存更改。这都是基于知道何时设置更改跟踪的基础上的。

如果你做任何将context.Configuration.AutoDetectChangesEnabled设置为false的操作,你需要在这之前将它设置回true,然后才能使这个方法起作用。我将它改为false以加快BulkInsert的速度,在我将其改回true之前,我没有看到任何使用这种方法的更新。

0