dotnet / dotnet/efcore

Raw SQL queries for unmapped types - how to define enum properties to map from strings?

Open
#33,206 22 comments 2 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

I was following the following guide: https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#raw-sql-queries-for-unmapped-types

I tried writing a query from a table that has some columns that are varchar or textual and are enum based values in the database.

```
public class CoreAlertStatus
{
public int Id { get; set; }
public required string Name { get; set; }
public int SortOrder { get; set; }


public EAlertColor AlertColor { get; set; }

public EAlertSymbol AlertSymbol { get; set; }
public int NextLevelCount { get; set; }
public int NextLevelId { get; set; }
public string NextLevelName { get; set; } = "";


public EOrgType NextLevelType { get; set; }
public int BypassCount { get; set; }
}
```

```
var result = await _context.Database.SqlQuery("...").ToListAsync();
```

I received the following error:

```
System.InvalidCastException: Can't convert VarChar to Int32
at MySqlConnector.Core.Row.GetInt32(Int32 ordinal) in /_/src/MySqlConnector/Core/Row.cs:line 247
at MySqlConnector.MySqlDataReader.GetInt32(Int32 ordinal) in /_/src/MySqlConnector/MySqlDataReader.cs:line 240
at lambda_method311(Closure, QueryContext, DbDataReader, Int32[])
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
```

Turns out the enum properties are trying to be converted from integers even though my column is string based. I normally handle with mapping the type in the OnModelCreating method. But since I am purposely trying to avoid mapping, I didn't know how to do this.

I eventually figured out if I add `[Column(TypeName = "VARCHAR(255)")]` it figures it out.
```
public class CoreAlertStatus
{
public int Id { get; set; }
public required string Name { get; set; }
public int SortOrder { get; set; }

[Column(TypeName = "VARCHAR(255)")] // required for ef core to interpret it as a string
public EAlertColor AlertColor { get; set; }

[Column(TypeName = "VARCHAR(255)")] // required for ef core to interpret it as a string
public EAlertSymbol AlertSymbol { get; set; }
public int NextLevelCount { get; set; }
public int NextLevelId { get; set; }
public string NextLevelName { get; set; } = "";

[Column(TypeName = "VARCHAR(255)")] // required for ef core to interpret it as a string
public EOrgType NextLevelType { get; set; }
public int BypassCount { get; set; }
}
```

Is this the correct way to specify this? Will this work across different databases? Is there a better database agnostic way of defining this?

I am using MYSQL.

EF Core version: 8.0.2
Database provider: Pomelo.EntityFrameworkCore.MySql 8.0.0
Target framework: NET 8.0
Operating system: Windows 11
IDE: Rider 2023.3.3

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.