【问题标题】:What is the simplest way to implement an Entity Framework 6 Add-or-Update method实现 Entity Framework 6 Add-or-Update 方法的最简单方法是什么
【发布时间】:2015-05-12 16:07:29
【问题描述】:

我有一个使用 Entity Framework 6 的项目,它为一堆不同的实体类型执行添加或更新(即 Upsert)。对于这些实体中的每一个,都有一个代理整数 ID(即主键)、一个用于外部查找的自然键(例如客户 ID)和一组描述性字段(例如名称、描述等)

我有一个 AddOrUpdate 方法,该方法查找自然键,在数据库中查找现有实体,并使用新值(如果存在)更新实体或创建新实体并将其添加到数据库中(如果它不存在)。

这是我想出的方法示例(注意“key”是自然键,而不是代理 ID):

public void AddOrUpdate(int key, string name)
{
    var customer = _database.Customers
        .FirstOrDefault(p => p.Key == key);

    var exists = customer != null;

    if (!exists)
        customer = new Customer();

    customer.Name = name;
    // Update other descriptive fields here

    if (!exists)
        _database.Customers.Add(customer);

    _database.Save();
}

代码运行正常,但总感觉有点乱。我很想知道是否有人有更好的方法来解决这个问题,它使用结构更简单、可读性更好、或者可以用更少的代码行(不牺牲可读性)完成,并且仍然很容易进行单元测试。

如果是这样,请发布您对上面代码的重构,以便我可以从您的示例中学习。

【问题讨论】:

  • 这似乎在Code Review 上会更好,因为它是工作代码。
  • 说实话,这是我第一次听说 Code Review。我会看看它,看看将我的问题迁移到那里是否更有意义。感谢您的信息!

标签: c# database entity-framework linq entity-framework-6


【解决方案1】:

EntityFramework 已经为你实现了这个,you can learn more about it here

void Main()
{
    using (AppContext context = new AppContext())
    {
        context.Users.AddOrUpdate(...);
    }
}

public class AppContext : DbContext
{
    public DbSet<User> Users { get; set; }
    
    
}

public class User 
{
    public string UserId { get; set; }
    public string Name { get; set; }
}

编辑

这个答案被否决了两次,因为它显然不是线程安全的。这可能会让一些人感到惊讶,但 Entity Framework 作为一个框架,并不是线程安全的。

MSDN DbContext - Thread Safety

此类型的任何公共静态(在 Visual Basic 中为共享)成员都是 线程安全。 不保证任何实例成员都是线程安全的。

基本上,我的解决方案的线程安全性是无关紧要的,因为任何跨并行线程使用实体框架 DbContext(特别是 SaveChanges / SaveChangesAsync 方法)都会给您带来开箱即用的问题。

【讨论】:

  • 这绝对是一个比我实现的更简单、更干净、更容易测试的解决方案。我很惊讶在今天之前我从未注意到这种扩展方法。我今天会试一试,看看我是否遇到任何问题。如果没有,我会将其标记为已接受的答案。感谢您的建议!
  • 可以在迁移之外使用该方法吗?它不在 EF 的主要部分中,这让我有点困扰。
  • @JohnSaunders,反映到实现中,我看不到任何会阻止您在迁移之外使用它的东西,并且应该与源自IDbSet 的任何东西一起使用。但是请记住,我没有测试过它,所以我可能是错的。
  • 该主题的其他线程警告说 AddOrUpdate 不是线程安全的。具有不同上下文的多个线程会重复记录。
  • 另外,这是否可以正确批量处理,还是每条记录都需要往返?
猜你喜欢
  • 2018-02-09
  • 2023-03-20
  • 2011-03-21
  • 2010-11-23
  • 1970-01-01
  • 2017-05-21
  • 2021-04-24
  • 1970-01-01
相关资源
最近更新 更多