[英]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?
I load data from a CSV file, I create entities on the fly then I add them to a List<T>
. 我从CSV文件加载数据,即时创建实体,然后将它们添加到List<T>
。
The following code takes a List<T>
and adds the entities to the right DbSet
. 以下代码采用List<T>
并将实体添加到右侧的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. 我想将其更改为仅在不存在时才添加实体,否则必须更新它。
What is the best way to accomplish this with Entity Framework Core? 使用Entity Framework Core实现此目标的最佳方法是什么? I believe I should use System.Reflection
to: 我相信我应该使用System.Reflection
来:
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. 该代码的运行速度比简单添加的速度慢3到4倍。
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
. 我发现的所有代码示例都是针对EF6
,都是基于ObjectContext
和IObjectContextAdapter
,似乎这种代码不再可以与EF Core
。
Instead of reflection, you could use the EF Core public (and some internal) metadata services to get the key values needed for Find
method. 取而代之的反射,你可以使用EF核心公共(和一些内部)元数据服务,以获得所需的键值Find
方法。 For setting the modified values you could use EntityEntry.CurrentValues.SetValues
method. 要设置修改后的值,可以使用EntityEntry.CurrentValues.SetValues
方法。
Something like this: 像这样:
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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.