为啥 dapper 在进行选择时为 Guid 返回全零但表中的 guid 值设置正确?

Posted

技术标签:

【中文标题】为啥 dapper 在进行选择时为 Guid 返回全零但表中的 guid 值设置正确?【英文标题】:Why is dapper returning all zero's for Guid when doing a select but the guid value in table is set correctly?为什么 dapper 在进行选择时为 Guid 返回全零但表中的 guid 值设置正确? 【发布时间】:2019-05-08 20:23:22 【问题描述】:

我正在使用 dapper 从表中查询数据,然后将其转换为对象。当它被转换为对象时,guid 属性设置为全零,但所有其他道具都设置正确。

public class UserStuff

    public int Id  get; set; 
    public Guid UId  get; set; 



public async Task<UserStuff> GetUserStuff(Guid uId)
  using(IDbConnection conn = Connection)
    string sQuery = "SELECT TOP 100 id, u_id " +
                    "FROM TestTable WHERE u_id = @u_id ";
    conn.Open();
    var result = await conn.QueryAsync<UserStuff>(sQuery, new  u_id = uId );
    return result.FirstOrDefault();
  

示例 SQL 数据:

标识 | u_id

5 | C9DB345B-D460-4D71-87E0-D9A3B5CE1177

它正在返回: id 为 5,guid 为全零

【问题讨论】:

这似乎是 Dapper 的一个已知问题,请参阅 github.com/StackExchange/Dapper/issues/447 和 ***.com/questions/5898988/…)。 我不确定您粘贴的链接是否与从 db 查询现有 guid 有关。它看起来像是用于创建指南。我正在尝试从 sql 查询 guid。 @ironman UserStuff 类中的属性名为 UId,但 SQL 表中的列名为 u_id。 Dapper 是否会自动进行一些名称匹配以将 u_id 转换为 UId?如果没有,您可以使用别名返回名称为UId 的值吗? @Progman 所以,你是说我的实体中的命名约定必须与表列名完全一致吗? @ironman 看起来有一个东西叫DefaultTypeMap.MatchNamesWithUnderscores。也许这会有所帮助。 【参考方案1】:

这里的核心问题是你的列名和属性名不同。因此,即使数据库作为 SQL 查询的结果返回值,它也不会映射到您的属性。由于您的属性的数据类型是 GUID,因此它保留其默认值 - 全为零。

Dapper 映射适用于约定;有点宽泛的话题来讨论。对于您的具体问题,您的列名和属性名应该匹配。如果它们不同,还有其他方法可以使映射正确发生。

我将在这里提出简单的解决方案:

    您可以指示 Dapper 在映射时忽略列名中的下划线。

    using Dapper;
    Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
    

    在项目启动时在某处设置此属性。

    在 SQL 查询中使用列别名。将您的 SQL 查询更改为如下所示:

    SELECT TOP 100 id, u_id as UId....
    

    这样,在不更改列名和属性名的情况下,您将能够正确填写属性,因为现在映射已更正。

    要么更改列名称以匹配属性名称,反之亦然。我认为这不切实际。

除了上述之外,dapper 还提供了一个自定义映射。

【讨论】:

【参考方案2】:

如果类型和属性相等,Dapper 将列与属性匹配

最简单的方法是调整查询

    string sQuery = "SELECT TOP 100 id, u_id as uid " +
                    "FROM TestTable WHERE u_id = @u_id ";

只是一个提示: 您无需手动打开连接。如果连接状态为closed,则在查询完成或失败后,Dapper 会为您执行此操作并关闭它。在更复杂的情况下,这可能是必要的,但在您的情况下则不是。

另一个提示: 不要在 SqlServer 中为列名使用下划线。按照 SqlServer 中的约定,我们应该使用大写的列名。

【讨论】:

以上是关于为啥 dapper 在进行选择时为 Guid 返回全零但表中的 guid 值设置正确?的主要内容,如果未能解决你的问题,请参考以下文章

为啥实体框架在直接选择语句中的执行速度比 Dapper 快 [关闭]

为啥我从 Dapper 返回的对象具有 null 和默认属性值?

带有 GUID Id 的简洁 CRUD

使用Dapper.SimpleCURD注意事项

DB2 - 使用带有字符串数组参数的 Dapper 选择查询将不会返回正确的结果

有时 Dapper 或 System.Data 不会为某些数据库(SQL Server 2012 和 2019)上的简单选择查询返回正确的结果