提供基于泛型类型集合的通用密钥比较

时间:2015-03-15 16:55:54

标签: c# linq generics expression-trees func

我为这样的几种类型创建了自己的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>是必需的,因为它将用于在datacontext中插入根对象。此方法基本上检索附加对象(如果存在)并使用最新值更新它(如果它没有)或将其作为新对象插入(如果它不存在)。然后返回此附加对象,以便它可以链接到多对多表中的根对象。

现在的问题是我有几个这样的集合(流派,海报,关键字等),每个类型的ID设置不同:有时它被称为TmdbId,有时{ {1}},有时Id。使用界面并将其全部重命名为Iso是一回事,但问题在于它们也是不同的类型:一些是Id,一些是int。< / p>

问题很简单:我如何将其变成更通用的东西以避免代码重复?

到目前为止,我一直在玩

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 does not work in my scenario

1 个答案:

答案 0 :(得分:1)

你可以尝试:

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));