【问题标题】:Incorporate Enum.GetName(...) into Linq Query将 Enum.GetName(...) 合并到 Linq 查询中
【发布时间】:2015-12-11 18:47:54
【问题描述】:

我有枚举:

public enum CmdType {
    [Display(Name = "abc")]
    AbcEnumIdentifier = 0,

    [Display(Name = "xyz")]
    XyzEnumIdentifier = 1,
    ...
}

我想将每个枚举的名称添加到我的查询中,但即使使用 .WithTranslations() 我也会收到此错误:

LINQ to Entities 无法识别方法 'System.String GetName(System.Type, System.Object)' 方法,并且该方法不能 翻译成商店表达式。

查询:

var joinedRecord =
    (
        from m in mTable
        join b in bTable on m.Id equals b.aRefId
        select new {
            aId = a.Id,
            aAttrib1 = a.Attrib1
            ...
            bCmdType = Enum.GetName(typeof(CmdType), b.CmdType)
        }
    ).WithTranslations();

如何在查询中使用Enum.GetName(...) 返回生成的值?

【问题讨论】:

    标签: c# entity-framework linq enums


    【解决方案1】:

    LINQ to entity 尝试将您的查询转换为 SQL,但它失败了,因为 SQL 中没有与 Enum.GetName 方法等效的方法。

    您需要具体化查询结果并将枚举值转换为它们在内存中的名称。

    var joinedRecords = (
        from m in mTable
            join b in bTable on m.Id equals b.aRefId
            select new {
                aId = a.Id,
                aAttrib1 = a.Attrib1
                ...
                bCmdType = b.CmdType
            }
    ).AsEnumerable() //Executes the query, further you have simple CLR objects
    .Select(o => new {
        aId = o.Id,
        aAttrib1 = o.Attrib1
        ...
        bCmdTypeName = Enum.GetName(typeof(CmdType), o.CmdType)
    });
    

    【讨论】:

    • 卢卡斯 - 谢谢!您的解决方案和来自@Luiso 的解决方案非常相似。将您的答案标记为我的答案,因为您的反应比心跳快。
    • 更正:@Luiso 来得更快,我很抱歉。谢谢你的好例子!
    【解决方案2】:

    您正在调用 Enum.GetName(typeof(CmdType), b.CmdType),它无法转换为 SQL,因为 Enum 定义不在数据库中,如果您查看行,您会看到有一个 int 而不是Enum 有问题的值。

    试试这个:

    var joinedRecord =
    (
        from m in mTable
        join b in bTable on m.Id equals b.aRefId
        select new {
            aId = a.Id,
            aAttrib1 = a.Attrib1
            ...
            bCmdType = b.CmdType
        }
    )
    .AsEnumerable() // or ToList()
    .Select( // map to another type calling Enum.GetName(typeof(CmdType), b.CmdType) )
    .WithTranslations();
    

    这样做的作用是通过调用AsEnumerable()ToList() 您不再处理IQueryable<T> 的实例(这是您的原始查询返回的内容,一旦您执行此操作,所有返回的对象都将是记忆中)。因此,一旦您在内存中有对象,您就可以像使用任何其他 C# 对象一样使用它们,这应该允许您使用您想要的方法。

    【讨论】:

    • Luiso - 一个很好的例子,谢谢。不幸的是,@lukas-kabrt 只是用相同的代码快了一点。 +1,但是对于一个很好的例子和解释。
    • 更正:将您的答案标记为我的答案,因为您的心跳响应更快。
    【解决方案3】:

    尝试转换为 AsEnumerable(),以便您可以使用 LINQ to Objects。 LINQ to Entities 将尝试将其转换为没有等效项的 SQL:

    var joinedRecord =
        (from m in mTable
        join b in bTable on m.Id equals b.aRefId)
        .AsEnumerable()
        .Select(x =>  new {
            aId = a.Id,
            aAttrib1 = a.Attrib1
            ...
            bCmdType = Enum.GetName(typeof(CmdType), b.CmdType)
        })
       .WithTranslations();
    

    http://www.lavinski.me/ef-linq-as-emumerable/

    【讨论】:

    • Steve,得到错误(在构建时)“查询主体必须以 select 或 group 子句结尾。”这是我在 SO 上提出问题之前遇到的问题 - 我不确定在仅使用“mTable 中的 m 加入 b ...”时要选择什么,但是谢谢您提供参考链接!跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多