我有一个使用Entity Framework 6的项目,它为一堆不同的实体类型执行Add-or-Update(即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();
}
代码工作正常,但总觉得有些乱。我很想知道是否有人用Entity Framework更好地解决这个问题,结构上更简单,读取更好,或者可以用更少的代码行完成(不牺牲可读性),并且仍然很容易进行单元测试。
如果是这样,请发布您对上述代码的重构,以便我可以从您的示例中学习。
答案 0 :(得分:2)
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; }
}
这个答案已被投票两次,因为显然它不是线程安全的。对于少数人来说这可能是一个惊喜,但实体框架作为一个框架,并不是线程安全的。
MSDN DbContext - Thread Safety
此类型的任何公共静态(在Visual Basic中为Shared)成员都是 线程安全。 不保证所有实例成员都是线程安全的。
基本上,我的解决方案的线程安全性是无关紧要的,因为在并行线程中使用Entity Frameworks DbContext(特别是SaveChanges / SaveChangesAsync方法)会给你带来问题,开箱即用。