【发布时间】:2015-03-15 16:55:54
【问题描述】:
我已经为以下几种类型创建了自己的 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。使用接口并将它们全部重命名为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.
【问题讨论】:
-
I have no access to the inner entity variable是什么意思?entity是foreach的变量 -
@xanatos:我的意思是从调用者的角度来看。理想情况下,我可以传递
x => x.TmdbId == entity.TmdbId之类的东西作为参数来指定应该比较的内容,但我不能这样做,因为我无法从该上下文访问实体。 -
Mmmh... 那么,如果您不知道 T 的类型,如何调用
InsertOrUpdate? (请注意,您应该使用Expression<Func<T, bool>>而不是Func<T, bool>)。如果您向我们展示您如何调用InsertOrUpdate,它将变得更加清晰 -
它目前被这样使用:
movie.Genres = new List<Genre>(InsertOrUpdate(movie.Genres));并且同样用于所有其他集合。我意识到我可能正在尝试做一些不可能的事情,所以我正在寻找解决此类问题的最佳方法。至于你的旁注:你手边有什么文献可供我阅读吗? -
不 :-) 我不读书... 遗憾的是我的注意力太短了:-(
标签: c# linq generics expression-trees func