Dapper 如何在同名的 2 列之间进行选择

问题描述 投票:0回答:3

我有一些继承的代码,它们使用 Dapper 将 SQL SELECT 映射到对象中。 SELECT 具有多个同名列(为简洁起见,省略了一些列)。

SELECT
    created_timestamp AS CreatedDate,
    imported_timestamp AS CreatedDate
FROM Orders
WHERE OrderId = @OrderId

数据分析显示,每条记录仅填充 2 个 CreatedDate 列之一。运行一些测试表明 Dapper 似乎选择了非 NULL CreatedDate。我找不到任何关于 Dapper 如何处理这种情况的文档。我可以依赖 Dapper 始终选择非 NULL 值吗?

dapper
3个回答
0
投票

Dapper 是(微)ORM,它应该用于数据库 CRUD 操作。

也就是说,您的业务逻辑应该去其他地方。实现非常简单。不要创建具有重复名称的列。使用 dapper 从数据库获取数据,并在其他地方应用您的业务逻辑,例如检查 null 或 else。

//Following is query
SELECT
    created_timestamp AS CreatedDate,
    imported_timestamp AS ImportedDate
FROM Orders
WHERE OrderId = @OrderId

//Following is your POCO/DTO
public class Order
{
    public int OrderId;//or Guid if that suits you
    public string CreatedDate;//or DateTime if that suits you
    public string ImportedDate;//or DateTime if that suits you
}

//Following is your business logic
Order order = orderService.GetOrder(orderId);
if(order.CreatedDate != null)
    //Do something
else if(order.ImportedDate != null)
    //Do something else

根据您的研究,即使 Dapper 选择非空列;在未来的版本中可能无法保证这一点。


0
投票

如果列名相同,它将选择第二个


0
投票

我知道这是一篇旧文章,但如果有人想知道,有一个解决方法,其中涉及使用 SqlDataReader 并按列索引/顺序手动映射列。 以下是我用来映射某个过程的结果的示例代码,该过程的某些列具有重复的名称:

    var resultList = new List<JobInfoModel>();
    await using var connection = new SqlConnection(_dbOptions.Value.DbConnectionString);
    await connection.OpenAsync(cancellationToken);
    using var command = new SqlCommand("JT_JobGet", connection);
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.AddWithValue("@ClientID", clientId);
    command.Parameters.AddWithValue("@UserID", userId);
    command.Parameters.AddWithValue("@JobID", jobId);
    
    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            try
            {
                var dataItem = new JobInfoModel
                {
                    Id = reader.GetInt32(0),
                    Oldid = reader.IsDBNull(1) ? null : reader.GetInt32(1),
                    ClientId = reader.GetInt32(2),
                    StatusId = reader.GetInt32(3),
                    SiteId = reader.GetInt32(4),
                    ContactName = reader.IsDBNull(5) ? null : reader.GetString(5),
                    ContactNumber = reader.IsDBNull(6) ? null : reader.GetString(6),
                    ContactEmail = reader.IsDBNull(7) ? null : reader.GetString(7),
                    Description = reader.GetString(8),
                    PriorityId = reader.GetInt32(9),
                    FaultCategoryId = reader.GetInt32(10),
                    ContractorId = reader.IsDBNull(11) ? null : reader.GetInt32(11),
                    ScheduledDate = reader.IsDBNull(12) ? null : reader.GetDateTime(12),
                    JobTypeId = reader.IsDBNull(13) ? null : reader.GetInt32(13),
                    ContractorEmailed = reader.IsDBNull(14) ? null : reader.GetString(14),
                    ContractorCalled = reader.IsDBNull(15) ? null : reader.GetString(15),
                    ContractorAcknowledgedJob = reader.IsDBNull(16) ? null : reader.GetString(16),
                    ContractorAttended = reader.IsDBNull(17) ? null : reader.GetString(17),
                    ContractorRef = reader.IsDBNull(18) ? null : reader.GetString(18),
                    CapexRef = reader.IsDBNull(19) ? null : reader.GetString(19),
                    RequestedByUserId = reader.IsDBNull(20) ? null : reader.GetInt32(20),
                    RequestedDate = reader.IsDBNull(21) ? null : reader.GetString(21),
                    CreatedByUserId = reader.IsDBNull(22) ? null : reader.GetInt32(22),
                    CreatedDate = reader.IsDBNull(23) ? null : reader.GetDateTime(23)
            };

            resultList.Add(dataItem);
        }
        catch (Exception ex)
        {
            _logger.LogCritical("Failed to map SP result to class {Exception}", ex);
        }
    }
}
await connection.CloseAsync();

IsDBNull 方法检查列是否可为空,否则在转换为所需类型时如果列值为空,则会抛出异常。

要运行 SQL 查询,您可能需要以这种方式创建读取器:

using var reader = await connection.ExecuteReaderAsync("SELECT created_timestamp AS CreatedDate, imported_timestamp AS CreatedDate FROM Orders WHERE OrderId = @OrderId");
© www.soinside.com 2019 - 2024. All rights reserved.