【问题标题】:Deleting and Inserting Entity with Entity Framework使用实体框架删除和插入实体
【发布时间】:2018-01-19 02:43:04
【问题描述】:

假设我有两个实体 E1E2 都共享相同的 Code 值。假设我要删除第一个并插入下一个:

Item.Delete(E1);
Item.Insert(E2);
Item.Save();

在哪里

public void Delete(Entity E) 
{
    var existingEntity = _context.EntityTable.SingleOrDefault(s => s.Code == E.Code);
    _context.EntityTable.Remove(existingEntity);
}

public void Insert(Entity E)
{
    var existingEntity = _context.EntityTable.FirstOrDefault(s => s.Code == E.Code);
    if (existingEntity != null){
        throw new ArgumentException("Item alread exists.")
    }

    var newEntity = CreateDbEntity(E); // Create Db Entity just convert the type. Nothing much here.
    _context.EntityTable.Add(newEntity);
}

public void Save()
{
    _context.SaveChanges();
}

这里的问题是,当我从_context 中的EntityTable 中删除E1 时,在我保存之前不会立即反映出来。因此,操作将失败,因为插入E2 仍然不成功,因为 E1 仍然存在。有没有解决这个问题的方法,EntityTable 确实反映了所做的更改?

【问题讨论】:

  • 为什么不将唯一条件留给 SQL 而不签入代码?
  • 在您查询一个是否存在和您调用 SaveChanges() 之间,也可以由另一个进程或线程插入一个。不要在代码中这样做。
  • 删除>保存>插入>保存..大声笑
  • @johnny5 这个例子很简单。但在软删除的情况下,SQL 中的唯一条件将不起作用。
  • @Husain,你为什么不检查实体的状态,看看它是否被删除? var existingEntity = _context.EntityTable.Any(s => s.Code == E.Code && _context.Entry(s).State != EntityState.Deleted);

标签: c# entity-framework


【解决方案1】:

每次操作后简单调用SaveChanges

您想在初始化上下文时进行事务(这确保两个操作都被执行):

_context = new FooEntities();
_transaction = _context.Database.BeginTransaction();

然后您的Save 方法将改为提交事务:

_transaction.Commit();

Dispose 上下文和事务不会有什么坏处,但我相信你已经这样做了 ;)


附带说明,因为无论如何你都会抛出异常:

if (existingEntity != null){
    throw new ArgumentException("Item alread exists.")
}

为什么不在代码列上创建unique constraint?这样数据库就会抛出异常;)

【讨论】:

  • 谢谢。为此,我试图避免两次往返 DB。唯一约束适用于这个简单的示例,但不适用于我的情况,因为我有一个软删除。在约束条件下,我必须解密从数据库中获取的异常,以便向 API 用户返回有用的消息。
  • 您可以在多个列之上设置唯一约束(例如 Code & IsDeleted)。此外,使用 ExceptionFilters 在 C# 6 中重新抛出更好的异常也非常容易。关于往返:通常阅读是昂贵的,因为这种情况比写作更频繁;)@Husain
【解决方案2】:

看起来你只是有一个操作顺序错误,这可能不是最有效的方法,但它应该可以解决你的问题。

Item.Delete(E1);
Item.Save();
Item.Insert(E2);
Item.Save();

按顺序调用他们。

或者您可以将 save 方法添加到您的 delete 和 insert 方法中,以便在执行每个方法时保存,您只需使用两行。

public void Delete(Entity E) 
{
    var existingEntity = _context.EntityTable.SingleOrDefault(s => s.Code == E.Code);
    _context.EntityTable.Remove(existingEntity);
    Save()
}

public void Insert(Entity E)
{
    var existingEntity = _context.EntityTable.FirstOrDefault(s => s.Code == E.Code);
    if (existingEntity != null){
        throw new ArgumentException("Item alread exists.")
    }

    var newEntity = CreateDbEntity(E); // Create Db Entity just convert the type. Nothing much here.
    _context.EntityTable.Add(newEntity);
    Save()
}

public void Save()
{
    _context.SaveChanges();
}

然后你可以这样称呼它

Item.Delete(E1);
Item.Insert(E2);

希望这会有所帮助!如果不让我知道,我会删除答案(我必须使用答案,因为我不能在 50 代表以下发表评论,否则我会在回答之前使用评论来获得更清晰的答案)干杯!

【讨论】:

  • 谢谢。一般的问题是我想避免两次去数据库。我在 Repo 中使用了 UOW 模式,这样业务逻辑对象就不需要多次进入数据库来插入不同的对象。
猜你喜欢
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多