如何在Entity Framework select子句中为值使用动态表达式

时间:2017-11-30 19:04:56

标签: c# entity-framework lambda linq-to-sql expression-trees

我不确定我是否正确地提出这个问题,或者是以一种可以理解的方式提出这个问题,但现在就是这样:

我试图找出一种在数据库上下文中选择值的动态方法。我在整个代码中使用了一些我称之为CodeTableValuePOCO的东西,并且我不想在每次需要时指定整个表达式(特别是查找CodeName的语法值)。所以,我尝试使用这样的表达式来动态生成它。

internal static Expression<Func<CodeTableValue, CodeTableValuePOCO>> GetCodeTableValueSelectorExpression(int languageId) {
        return x => new CodeTableValuePOCO
        {
            Code = x.Code,
            // Check if there are any translations for the code name
            CodeName = x.Translations != null
                        // If there are, check if there is a translation for user's language
                        ? x.Translations.LanguageTranslationTexts.Count(t => t.Language_ID == languageId) > 0
                            // If there is a translation, take the first for the given language
                            ? x.Translations.LanguageTranslationTexts.FirstOrDefault(t => t.Language_ID == languageId).Text
                            // Else, default to codeName
                            : x.CodeName
                        // Else, default to codeName
                        : x.CodeName,
            CodeTableId = x.CodeTable.CodeTableID,
            Id = x.CodeTableValueID,
            Key = x.CodeTable.Key,
            ParentId = x.ParentID
        };
    }

但是,我无法弄清楚如何在我的代码中使用上面的表达式。我认为如果我只是在寻找一个CodeTableValuePOCO它会起作用 ,但CodeTableValuePOCO嵌入较大的选择中,如下例所示。显然,它不起作用,因为程序期望CodeTableValuePOCO,但是获得表达式。

using (MyDbContext db = new MyDbContext()) {

    return db.Notifications
        .Where(x => x.id == 1)        
        .Select(x => new NotificationPOCO
        {
            Id = x.Id,
            Message = x.Message,
            //This part is, obviously, not working
            Type = code.GetCodeTableValueSelectorExpression(2)
         })
         .ToList();
        }
}

1 个答案:

答案 0 :(得分:2)

在其他表达式中使用表达式没有自然的C#编译时支持。

您需要一些表达式组合库 - 例如LINQKit。它解释了该问题,并使用自定义InvokeAsExpandable扩展方法解决了该问题。您的案例中的解决方案是这样的(安装包后):

using LinqKit;

using (MyDbContext db = new MyDbContext()) {
    var codeTableValueSelector = GetCodeTableValueSelectorExpression(2); 
    return db.Notifications.AsExpandable()
        .Where(x => x.id = 1)        
        .Select(x => new NotificationPOCO
        {
            Id = x.Id,
            Message = x.Message,
            Type = codeTableValueSelector.Invoke(x) // or x.CodeTable? not sure from the sample code
        })
        .ToList();
}