EF Core LINQ无法转换架构子方法

mzsu5hc0  于 2023-05-11  发布在  其他
关注(0)|答案(1)|浏览(156)

我们有一个BaseSchema类,其中包含另一个模式的IEnumerable,该模式包含应用程序使用的每种语言的数据。
我们在基本模式中编写了一个帮助器方法,它将获取所提供语言的描述模式中的属性,或者如果没有找到,则获取第一个具有值的属性。

return await Context.Allergies
    .Include(allergy => allergy.Descriptions)
    .AsNoTracking()
    .Select(allergy => new SynchronizableAllergyViewModel
    {
        Id = allergy.Id.ToString(),
        IsCommon = allergy.IsCommon,
        Name = allergy.GetTranslatedString(d => d.Name, Language),
    })
    .ToListAsync();
public string GetTranslatedString(Func<TMultilingualSchema, string> stringParam, 
    TLanguageSchemaId languageId)
{
    return Descriptions
        .OrderBy(d => d.LanguageId.Equals(languageId) ? 0 : 1)
        .Select(stringParam)
        .FirstOrDefault(d => !string.IsNullOrWhiteSpace(d)) ?? string.Empty;
}

我们在.NET 6.0上使用EF Core 6.0.16在SQL Server上。
当使用helper方法时,我们得到
无法翻译LINQ表达式'd => d.Name'
但是,我们可以就地复制方法体并获得预期的结果

return await Context.Allergies
    .Include(allergy => allergy.Descriptions)
    .AsNoTracking()
    .Select(allergy => new SynchronizableAllergyViewModel
    {
        Id = allergy.Id.ToString(),
        IsCommon = allergy.IsCommon,
        Name = allergy.Descriptions.OrderBy(d => d.LanguageId.Equals(Language) ? 0 : 1)
            .Select(d => d.Name)
            .FirstOrDefault(d => !string.IsNullOrWhiteSpace(d)) ?? string.Empty
    })
    .ToListAsync();

我们尝试将方法更改为使用表达式,并从参数名称构建表达式,但没有成功。
当我们使用EF Core 7.0.5在.NET 7上尝试“复制”解决方案时,它给出了与方法调用相同的结果。

qij5mzcb

qij5mzcb1#

你可以用LINQKit来实现
先决条件:
1.安装软件包LinqKit.Microsoft.EntityFrameworkCore。根据EF Core主要版本选择适当的版本。
1.通过以下选项激活LINQKit

builder
    .UseSqlServer(connectionString)
    .WithExpressionExpanding(); // enabling LINQKit extension

按以下方式修改您的方法:

public class Allergy
{
    ... // other properties

    [Expandable(nameof(GetTranslatedStringImpl))]
    public string GetTranslatedString(Func<TMultilingualSchema, string> stringParam, 
        TLanguageSchemaId languageId)
    {
        throw new NotImplementedException();
    }

    private static Expression<Func<Allergy, Func<TMultilingualSchema, string>, TLanguageSchemaId, string>> GetTranslatedStringImpl()
    {
        return (allergy, stringParam, languageId) => allergy.Descriptions
                .OrderBy(d => d.LanguageId.Equals(languageId) ? 0 : 1)
                .Select(stringParam)
                .FirstOrDefault(d => !string.IsNullOrWhiteSpace(d)) ?? string.Empty    
    }
}

之后,您可以在LINQ查询中使用您的方法。

相关问题