Home > Net >  The LINQ expression 'FirstOrDefault()' could not be translated and will be evaluated local
The LINQ expression 'FirstOrDefault()' could not be translated and will be evaluated local

Time:04-21

In seeding, I use collection of jsons to read it and insert in DB.

I using this function

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

And call it as this code.

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

CodePudding user response:

The problem (I believe) is in the uniqueProperty delegate, which is declared as a Func delegate. LINQ cannot translate compiled functions into parts of the SQL instruction, and therefore gives up the effort, letting the predicate resolve at the calling end.

The direct result of such unfortunate even is that all the data from the database would be transferred to the caller prior to subduing them to the function.

You may try by accepting an expression evaluating to bool in place of the Func delegate.

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

The predicate would have to complete comparison of unique properties:

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

It is probably possible to incorporate an expression which isolates an equatable property as well, and then to perform the equality test directly in the Where clause, but that would require a bit more work.

  • Related