C# 使用Dapper将字符串映射到guid
我正在使用Dapper开发一些需要访问PostgreSQL数据库的负载测试工具。此特定版本的PostgreSQL本机不支持GUID,因此GUID值存储为32个字符串。使用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为特定类型生成备用绑定代码,因此
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);
}
}