I load data from a CSV file, I create entities on the fly then I add them to a List<T>
.
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.
What is the best way to accomplish this with Entity Framework Core? I believe I should use System.Reflection
to:
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.
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
.
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.
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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.