Dapper枚举映射

18

我需要帮助将枚举映射到Dapper和Oracle中。

我在Oracle中有一个类型为NUMBER(1)的字段,必须将其转换为实体中的枚举。

public Status Status { get; set; }

状态是一个枚举类型:

-->

Status是一个枚举类型:

public enum Status
{
    [Description("Inactive", "0")]
    Inactive = 0,

    [Description("Active", "1")]
    Active = 1,
 }

如何使用Dapper进行映射?


1
Dapper会自动完成这个操作,只需确保你的查询返回的数字字段与实体类中的Status属性名称相同即可。 - Glen Thomas
4个回答

19

枚举应该可以轻松处理整数或字符串表示。如果它不能正常工作,您需要更具体地了解它抛出的任何异常。例如,我在想,也只是纯属猜测,Oracle想要将数字视为64位,我想知道枚举映射代码是否可以处理所有各种类型的数字转换。如果无法处理,那就是一个bug。

所以:它能正常工作吗?


关于“枚举应该JustWork”的问题,我正在努力解决。我只是定义了一个标准的枚举,尝试将其插入到MySQL表中,其中该字段被定义为INT(11)。但是我一直收到SQL错误,告诉我该字段不能为空。所以Dapper将我的枚举映射为空值而不是整数? - ScottTx
@ScottTx 你有例子吗? - Marc Gravell
进一步测试后,我发现问题并不是枚举类型的问题。我在类中切换到 int 数据类型,但仍然遇到了相同的问题。我使用的是 Devart MySql 驱动程序。我切换到从 Github 下载的 MySqlConnector 异步驱动程序后,一切都开始正常工作了。无论是枚举还是整数。因此,Devart 提供程序肯定存在某些问题。但是,我可以使用 MySqlConnector,所以我的问题得到了解决。 - ScottTx
我正在使用Dapper与Mysql数据库,虽然插入命令可以正常工作,但更新命令却无法正常工作。我的数据库中的枚举是字符串值(Mysql),但显然,Dapper试图将数字值传递给它们。 - Cyril Gupta
显然,在枚举映射规则中有一个例外,当例如Query<T>()方法的类型参数本身是一个枚举时:我尝试从列中选择字符串值,并将其作为枚举的IEnumerable返回,但它会抛出ArgumentException,声称“传递的值必须是枚举基础或枚举的基础类型,例如Int32”。我已经检查了查询的输出并确保它仅返回与枚举字段名称匹配的字符串值。在只有一个用例中不得不诉诸于Query<string>().Select(Enum.Parse)有点尴尬。 - Tom Lint
嗯,这仍然应该被视为一个 bug,Dapper 在将枚举转换为字符串以插入数据库时无法正常工作,这使得在 PostgreSQL 中使用它变得非常麻烦。它在将数据作为字符串>枚举拉出时运行良好。但似乎没有办法让枚举强制转换为字符串而不是整数。 - Phill

10

为了明确其他答案中提供的有用建议,您的数据库可能将数据存储在名为StatusId 的列中,而您的对象属性可能只是Status

我通常通过在SQL查询中使用别名来解决这个问题:

SELECT StatusId AS Status FROM Table

Dapper隐式理解如何将一个int数据库字段映射到C#枚举。 我通常会给我的枚举值分配显式值,以使事情尽可能清晰,例如:

public enum Status
{
   Active = 1,
   Inactive = 2
}

你的实体有一个枚举类型的状态属性吗?它对于插入和更新操作都有效吗? - Kiquenet

1
我无法在使用Dapper时让可空枚举正常工作。 为了解决这个问题,我创建了两个类:一个对象模型和一个 SQL 模型。 SQL 模型是对象模型的简化版本,其中使用枚举作为它们在数据库中保存的字符串。 对象模型具有以 SQL 模型为输入的构造函数。
class ThingSQLModel
{
    public int? Id;

    public String? ThingType;

 ....


}

class Thing
{
    public int? Id;

    public EnumThingType? ThingType{ get; set; }

 ....

    public Thing(ThingSQLModel)
    {
        Id = output.Id;

        ThingType= EnumHelper.TryParseNullable<EnumThingType>(output.ThingType);
    }
}

对于TryParseNullable<EnumThingType>,请参见: 将值解析为可空枚举

也许有一种更好的方法,通过显式地覆盖此类型的默认解析方式?嗯,我会进行实验并回答。


1
除了现有的答案之外,还有另一种特殊情况。
我发现如果枚举映射到模型内部的属性,并且您的 Query 是该模型类型,Dapper 会自动映射枚举。
然而,当您直接查询 Query 时,它会抛出异常并期望从数据库中得到一个 int32 值。
为了解决这个问题,我只需创建一个小的 EnumWrapper,如下所示:
public class EnumWrapper<T> where T:struct
{
    public T Value { get; set; }
}

然后继续像这样查询:
    var sql = @"SELECT E.[Status] AS [Value] FROM [Exmaple].Example E";

    var connection = await this.GetConnection();
    
    var status = await connection.QuerySingleAsync<EnumWrapper<TheEnum>>(sql);

    return status.Value;

SQL别名与EnumWrapper中的属性匹配非常重要。在这种情况下,它是Value


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接