c# - 提供基于通用类型集合的通用键比较

标签 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> 的返回类型是必需的,因为它将用于在数据上下文中插入根对象。此方法基本上检索附加对象(如果存在)并使用最新值更新它(如果存在)或将其作为新对象插入(如果不存在)。之后返回这个附加对象,这样它就可以链接到多对多表中的根对象。

现在的问题是我有几个这样的集合(流派、海报、关键字等)并且每个类型的 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/

相关文章:

c# - 在 linq 中返回所有具有相同名称的 xml 项

c# - 在 linq 中使用 groupby 进行多次连接

c# - 迭代 XML 时 Linq 重复元素

c# - Linq OrderBy int 属性不起作用

具有默认大小或提供一个的 C# 通用列表

c# - WPF自定义控件设计错误

c# - 如何使用 Entity Framework code-first 和更新的数据库模型版本

c# - IndexOf 谓词?

c# - '<null>' 类型的值不能用作默认参数,因为没有到 'T' 类型的标准转换

c# - 通用接口(interface)引用如何接受非通用对象?