LINQ 表达式 'FirstOrDefault()' 无法翻译,将在本地求值

The LINQ expression 'FirstOrDefault()' could not be translated and will be evaluated locally

在做种时,我使用 json 集合来读取它并插入到数据库中。

我在用这个功能

private void Seed<T, T2>(DbSet<T> dataSet, Func<T, T2> uniquProperty) where T : class, ISeedableEntity<T>
{
    var separtor = Path.DirectorySeparatorChar;
    var tableName = Model.FindEntityType(typeof(T)).SqlServer().TableName;
    var baseDir = Assembly.GetExecutingAssembly().Location;
    baseDir = Path.GetDirectoryName(baseDir);
    var filePath = $"{baseDir}{separtor}Data{separtor}{tableName}.json";
    if (File.Exists(filePath))
    {
        var data = File.ReadAllText(filePath);
        var items = JsonConvert.DeserializeObject<List<T>>(data);
        foreach (var item in items)
        {
            var found = dataSet.Where(
                a => uniquProperty(a).Equals(uniquProperty(item))).FirstOrDefault();

            if (found != null)
            {
                found = found.Update(item);
                dataSet.Update(found);
            }
            else
                dataSet.Add(item);
        }
        SaveChanges();
    }
}

并以此代码命名。

Seed(CreditRatings, a => a.Id);

问题(我相信)出在 uniqueProperty 委托中,它被声明为 Func 委托。 LINQ 无法将已编译的函数转换为 SQL 指令的一部分,因此放弃了努力,让谓词在调用端解析。

这种不幸的直接结果甚至是数据库中的所有数据都将在将它们制服到函数之前传输给调用者。

您可以尝试接受计算结果为 bool 的表达式来代替 Func 委托。

private void Seed<T, T2>(DbSet<T> dataSet, Expression<Func<T, T, bool>> predicate)
where T : class, ISeedableEntity<T>
{
    // ...
}

谓词必须完成唯一属性的比较:

Expression<Func<T, T, bool>> seed = (a, b) => a.Id.Equals(b.Id);

可能也可以合并一个表达式来隔离等式 属性,然后直接在 Where 子句中执行相等性测试,但这需要更多的工作.