我已经创建了自己的 InsertOrUpdate()
像这样的一些类型的实现:
public IEnumerable<Genre> InsertOrUpdate(IEnumerable<Genre> genres)
{
foreach (var genre in genres)
{
var existingGenre = _context.Genres.SingleOrDefault(x => x.TmdbId == genre.TmdbId);
if (existingGenre != null)
{
existingGenre.Update(genre);
yield return existingGenre;
}
else
{
_context.Genres.Add(genre);
yield return genre;
}
}
_context.SaveChanges();
}
IEnumerable<T>
的返回类型是必需的,因为它将用于在数据上下文中插入根对象。此方法基本上检索附加对象(如果存在)并使用最新值更新它(如果存在)或将其作为新对象插入(如果不存在)。之后返回这个附加对象,这样它就可以链接到多对多表中的根对象。
现在的问题是我有几个这样的集合(流派、海报、关键字等)并且每个类型的 ID 设置不同:有时它被称为 TmdbId
, 有时 Id
有时 Iso
.使用接口(interface)并将它们全部重命名为 Id
是一回事但问题在于它们也是不同的类型:有些是 int
有些是string
.
问题很简单:我如何将它变成更通用的东西来避免这种代码重复?
到目前为止我一直在玩弄
public IEnumerable<T> InsertOrUpdate<T>(IEnumerable<T> entities, Func<T, bool> idExpression) where T : class
{
foreach (var entity in entities)
{
var existingEntity = _context.Set<T>().SingleOrDefault(idExpression);
if (existingEntity != null)
{
_context.Entry(existingEntity).CurrentValues.SetValues(entity);
yield return existingEntity;
}
else
{
_context.Set<T>().Add(entity);
yield return entity;
}
}
_context.SaveChanges();
}
但显然这行不通,因为我无法访问内部 entity
多变的。旁注:IDbSet<T>().AddOrUpdate()
does not work in my scenario .
最佳答案
你可以试试:
public IEnumerable<T> InsertOrUpdate<T>(IEnumerable<T> entities, Func<T, object[]> idExpression) where T : class
和
var existingEntity = _context.Set<T>().Find(idExpression(entity));
用类似的东西调用
movie.Genres = new List<Genre>(InsertOrUpdate(movie.Genres, x => new object[] { x.Id }));
(请注意,返回 IEnumerable<>
的方法非常 危险...如果您不枚举它,例如
InsertOrUpdate(movie.Genres, x => x.Id);
那么该方法将不会完全执行,因为它将“按需”延迟执行)
如果只有单键表,可以改成:
public IEnumerable<T> InsertOrUpdate<T>(IEnumerable<T> entities, Func<T, object> idExpression) where T : class
和
var existingEntity = _context.Set<T>().Find(new object[] { idExpression(entity) });
和
movie.Genres = new List<Genre>(InsertOrUpdate(movie.Genres, x => x.Id));
关于c# - 提供基于通用类型集合的通用键比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29063445/