Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Dapper将字符串映射到guid_C#_Sql_Orm_Dapper - Fatal编程技术网

C# 使用Dapper将字符串映射到guid

C# 使用Dapper将字符串映射到guid,c#,sql,orm,dapper,C#,Sql,Orm,Dapper,我正在使用Dapper开发一些需要访问PostgreSQL数据库的负载测试工具。此特定版本的PostgreSQL本机不支持GUID,因此GUID值存储为32个字符串。使用someGuid将值转换为字符串。对于字符串(“N”),可以使用新Guid(stringValueFromColumn)将值转换回Guid 我的问题是如何让Dapper读取字符串并将其转换回GUI 我试图修改DbType映射,但没有成功。我一起破解了一个解决方案。据我所知,没有办法指示Dapper为特定类型生成备用绑定代码,因此

我正在使用Dapper开发一些需要访问PostgreSQL数据库的负载测试工具。此特定版本的PostgreSQL本机不支持GUID,因此GUID值存储为32个字符串。使用
someGuid将值转换为字符串。对于字符串(“N”)
,可以使用
新Guid(stringValueFromColumn)
将值转换回Guid

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


我试图修改DbType映射,但没有成功。

我一起破解了一个解决方案。据我所知,没有办法指示Dapper为特定类型生成备用绑定代码,因此我修改了
GetClassDeserializer
方法,如果属性是guid,则强制unbox类型为string。 接下来,我重新使用了为枚举生成构造函数调用的代码

下面是修改后的代码段(从rf6d62f91f31a版本的第761行开始):


也许最简单的方法(不必等待整洁)是拥有第二个属性:

public Guid Foo {get;set;}

public string FooString {
    get { return Foo.ToString("N"); }
    set { Foo = new Guid(value); }
}
SELECT UserID AS UserIDString FROM....
在查询中,将列别名为
FooString


当然,这就引出了一个问题:dapper是否应该支持此类事情的私有属性?对此我说:可能。

这是一个老问题,但我觉得它需要更新,因为Dapper现在支持私有属性,Marc在中提到了私有属性

然后在SQL中为ID列指定一个别名,以将其映射到私有属性而不是实际属性:

public Guid Foo {get;set;}

public string FooString {
    get { return Foo.ToString("N"); }
    set { Foo = new Guid(value); }
}
SELECT UserID AS UserIDString FROM....

我正在使用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);
    }
}
我希望这能有所帮助

我不必在查询中使用别名。我所做的:

public abstract class Entity
{
    protected Entity()
    {
        Id = Guid.NewGuid().ToString();
    }

    public string Id
    {
        get; set; 
    }
}

在您的表中,类型为varchar,看起来PostgreSQL中已经有UUID类型了。但是@Cpt.Ohlund对于2020年的MySQL/MariaDB来说仍然很好

但解决方案本身可能会带来问题

VARCHAR(36)
用于
System.Guid
时,会引发以下异常:

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

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

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

System.InvalidCastException:无法强制转换类型为的对象 “System.Guid”以键入“System.String”

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


因此,简单的答案是在MySQL和MariaDB中使用
CHAR(36)
,这样就行了

但如果需要处理任何字符串类型的列,则必须使用改进的@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);
    }
}
公共类MySqlGuidTypeHandler:SqlMapper.TypeHandler { 公共覆盖无效设置值(IDbDataParameter参数,Guid) { parameter.Value=guid.ToString(); } 公共重写Guid解析(对象值) { //Dapper可以传递Guid而不是字符串 if(值为Guid) 返回(Guid)值; 返回新的Guid((字符串)值); } }
并使用
SqlMapper.AddTypeHandler()

注册它。类型强制是我故意避免的事情,你介意在我们的bug追踪器上发布一个功能请求,看看它是否适合,记住如果postgres中的guid恰好是31个字符长的话,将会发生惊人的爆炸…@Sam-meh,GIGO;就我个人而言,这不会让我太烦恼。还有一点是,L2S在这里进行了一些转换(包括通过名称作为字符串的枚举)。@Sam谢谢,我已经发布了功能请求。好吧,这比破解Dapper要干净一点。允许设置私有属性(或字段)将非常好。@Marnix-是的,我打算添加those@Marnix-现在都存在了,顺便说一句(在源代码中-我还没有取消部署nuget包)@MarcGravel你能用私有财产的例子更新你的答案吗?@MarcGravel谢谢。我在SQLite中遇到了这个问题,但我尝试在Contrib库中使用Get。这意味着我将不得不使用Query。尽管您在问题中突出提到了这一点,但我没有提到您使用的数据库“本机不支持guid”。值得注意的是,在这样做的数据库中,可以将tSQL(或类似)中的UNIQUEIDENTIFIER映射到C#()中的Guid。不知道为什么这不是最上等的答案,它工作得非常完美,比其他方法更正式。这比我的解决方案更好。真的很好,我只是在SqliteWork上使用了它作为魅力,谢谢!最简单的解决方案!有人请把这个标记为正确答案。此方法还正确处理匿名查询参数中的映射GUID字段。
RemoveTypeMap
调用也很重要而不是
UserID=value?否则我认为你有一个∞ 环
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);
    }
}