Jasel
Jasel

Reputation: 564

Incorporate Enum.GetName(...) into Linq Query

I have the enumeration:

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

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

I'd like to get the names of each enumeration into my query, but even using .WithTranslations() I'm getting this error:

LINQ to Entities does not recognize the method 'System.String GetName(System.Type, System.Object)' method, and this method cannot be translated into a store expression.

The query:

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

How do I return a generated value using Enum.GetName(...) within the query?

Upvotes: 7

Views: 6655

Answers (3)

Lukas Kabrt
Lukas Kabrt

Reputation: 5489

LINQ to entities tries to translate your query to SQL and it fails to do so, because there is no equivalent of the Enum.GetName method in SQL.

You need to materialize the results of the query and convert the enum values to their name in the memory.

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

Upvotes: 6

Luiso
Luiso

Reputation: 4113

You are calling Enum.GetName(typeof(CmdType), b.CmdType) which cannot be translated to SQL as the Enum definition is not in the DB if you take a look at your rows you'll see there is an int instead of the name of the Enum value in question.

Try this:

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

What this does is that by calling AsEnumerable() or ToList() you are no longer processing an instance of IQueryable<T> (which is what your original query returns, on the bad side once you do this all returned objects will be on memory). So once you have objects in memory you can use them just as any other C# object which should allow you to use the methods you want.

Upvotes: 5

Steve Greene
Steve Greene

Reputation: 12304

Try casting to AsEnumerable() so you can use LINQ to Objects. LINQ to Entities will try to translate it to SQL for which there is no equivalent:

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

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

Upvotes: 2

Related Questions