实体框架核心:检查一个通用实体是否已经在dbset中然后添加或更新的最快方法是什么? [英] Entity Framework Core: What is the fastest way to check if a generic entity is already in the dbset and then add or update it?
问题描述
我从CSV文件加载数据,我即时创建实体,然后将它们添加到列表< T>
。
I load data from a CSV file, I create entities on the fly then I add them to a List<T>
.
以下代码采用列表< T>
,并将实体添加到右侧 DbSet
。
The following code takes a List<T>
and adds the entities to the right DbSet
.
public static void AddEntities<T>(List<T> entities, DbContext db) where T :class
{
using (db)
{
var set = db.Set<T>();
foreach(T e in entities)
{
set.Add(e);
}
db.SaveChanges();
}
}
我想更改它添加实体只有在不存在的情况下,否则必须更新它。
I'd like to change it to add the entity only if it doesn't exist, otherwise it has to update it.
使用Entity Framework Core完成此项工作的最佳方法是什么?
我相信我应该使用 System.Reflection
来:
What is the best way to accomplish this with Entity Framework Core?
I believe I should use System.Reflection
to:
- 获取至少该ID,但是最好通过密钥获取dbset的所有密钥,以查找一个实体是否已经在DbSet中。
- 如果发现,然后使用新实体的值更新它,否则将其添加到集合
这样的东西: p>
Something like this:
public static void AddEntities<T>(List<T> entities, DbContext db) where T :class
{
using (db)
{
var set = db.Set<T>();
foreach(T e in entities)
{
var idProperty = e.GetType().GetProperty("ID").GetValue(e,null);
var obj = set.Find(idProperty);
if (obj==null)
{
set.Add(e);
}
else
{
var properties = (typeof(T)).GetProperties();
foreach (var p in properties)
{
var value = e.GetType().GetProperty(p.Name).GetValue(e,null);
obj.GetType().GetProperty(p.Name).SetValue(obj,value);
}
}
}
db.SaveChanges();
}
}
代码运行速度比简单添加。
The code runs from 3 to 4 times slower than the simple add.
有更快的方法吗?根据 ObjectContext
和 IObjectContextAdapter ,我发现的所有代码示例都是
EF6
/ code>,似乎这种代码不再使用 EF Core
。
Is there a faster way? All the code examples I am finding are all for EF6
, based on ObjectContext
and IObjectContextAdapter
and it seems this kind of code do not longer work with EF Core
.
推荐答案
而不是反思,您可以使用EF Core公开(和一些内部)元数据服务来获取 Find
方法所需的键值。要设置修改后的值,您可以使用 EntityEntry.CurrentValues.SetValues
方法。
Instead of reflection, you could use the EF Core public (and some internal) metadata services to get the key values needed for Find
method. For setting the modified values you could use EntityEntry.CurrentValues.SetValues
method.
像这样:
using Microsoft.EntityFrameworkCore.Metadata.Internal;
public static void AddEntities<T>(List<T> entities, DbContext db) where T : class
{
using (db)
{
var set = db.Set<T>();
var entityType = db.Model.FindEntityType(typeof(T));
var primaryKey = entityType.FindPrimaryKey();
var keyValues = new object[primaryKey.Properties.Count];
foreach (T e in entities)
{
for (int i = 0; i < keyValues.Length; i++)
keyValues[i] = primaryKey.Properties[i].GetGetter().GetClrValue(e);
var obj = set.Find(keyValues);
if (obj == null)
{
set.Add(e);
}
else
{
db.Entry(obj).CurrentValues.SetValues(e);
}
}
db.SaveChanges();
}
}
这篇关于实体框架核心:检查一个通用实体是否已经在dbset中然后添加或更新的最快方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!