使用Dapper将字符串映射到guid

Mar*_*len 11 c# sql orm dapper

我正在使用Dapper来敲除一些需要访问PostgreSQL数据库的负载测试工具.PostgreSQL的这个特定版本本身不支持GUID,因此GUID值存储为32个字符串.使用someGuid.ToString("N")转换回Guid 的值,可以使用转换回Guid new Guid(stringValueFromColumn).

我的问题是如何让Dapper读取字符串并将其转换回Guids?

我尝试修改DbType映射,但这不起作用.

Mar*_*ell 21

也许最简单的方法(没有等待精巧)是有第二个属性:

public Guid Foo {get;set;}

public string FooString {
    get { return Foo.ToString("N"); }
    set { Foo = new Guid(value); }
}
Run Code Online (Sandbox Code Playgroud)

在您的查询中,将列别名为FooString.

当然,这会引发一个问题:应该为这种类型的东西支持私有属性吗?我说的话:可能.


Cpt*_*und 12

我知道这是一个老问题,但是对于像今天这样绊脚石的任何人,我都会发布我的解决方案。

我正在使用MySql,但由于将Guid存储为字符串,因此存在相同的问题。为了修复映射而不必别名列,我使用了以下内容:

public class MySqlGuidTypeHandler : SqlMapper.TypeHandler<Guid>
{
    public override void SetValue(IDbDataParameter parameter, Guid guid)
    {
        parameter.Value = guid.ToString();
    }

    public override Guid Parse(object value)
    {
        return new Guid((string)value);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的Startup.cs中:

public void ConfigureServices(IServiceCollection services)
    {
        SqlMapper.AddTypeHandler(new MySqlGuidTypeHandler());
        SqlMapper.RemoveTypeMap(typeof(Guid));
        SqlMapper.RemoveTypeMap(typeof(Guid?));
    }
Run Code Online (Sandbox Code Playgroud)

  • 有人**请**将此标记为正确答案。此方法还可以正确处理匿名查询参数中的映射 GUID 字段。`RemoveTypeMap` 调用也很重要。 (2认同)
  • 在 MySql 中,还可以将列创建为二进制 (16) 并在此 TypeHandler 中使用 `guid.ToByteArray()` 和 `new Guid((byte[])value)`。 (2认同)

Jac*_*ger 5

这是一个老问题,但我觉得它需要更新,因为 Dapper 现在支持私有属性,Marc 在他的回答中引用了私有属性。

private String UserIDString { get; set; }
public Guid UserID
{
    get
    {
        return new Guid(UserIDString);
    }
    private set
    {
        UserID = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在 SQL 中给你的 ID 列一个别名,将它映射到私有属性而不是实际属性:

SELECT UserID AS UserIDString FROM....
Run Code Online (Sandbox Code Playgroud)


Sup*_*upa 5

看起来PostgreSQL中已经有UUID类型了。但是@Cpt.Ohlund 的解决方案在 2020 年仍然非常适合 MySQL/MariaDB。

但解决方案本身可能会导致问题。

VARCHAR(36)用于System.Guid以下异常被抛出:

System.InvalidCastException:从“System.String”到“System.Guid”的无效转换。

@Cpt.Ohlund 的解决方案使它起作用。

但是如果该列是CHAR(36)那么它会System.Guid自动映射到!如果应用@Cpt.Ohlund 的解决方案,则会出现另一个例外:

System.InvalidCastException:无法将“System.Guid”类型的对象转换为“System.String”类型。

异常是由System.Guid传递给Parse(object value)而不是字符串的实例引起的。


所以简单的答案是CHAR(36)在 MySQL 和 MariaDB 中使用,它会起作用。

但是,如果您需要处理列的任何字符串类型,则必须使用改进的 @Cpt.Ohlund 解决方案:

public class MySqlGuidTypeHandler : SqlMapper.TypeHandler<Guid>
{
    public override void SetValue(IDbDataParameter parameter, Guid guid)
    {
        parameter.Value = guid.ToString();
    }

    public override Guid Parse(object value)
    {
        // Dapper may pass a Guid instead of a string
        if (value is Guid)
            return (Guid)value;

        return new Guid((string)value);
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用SqlMapper.AddTypeHandler().