c# - 如何使用 dapper 返回包​​含其他类型列表的类型?

标签 c# dapper

如何使用 dapper 在一次查询中选择所有 SpaceShips 及其 Sightings

我有以下对象:

public class SpaceShip
{
    public int Id { get; set; }
    public string DriveType { get; set; }
    public List<Sighting> Sightings { get; set; }
}
public class Sighting
{
    public int Id { get; set; }
    public double Lat { get; set; }
    public double Lon { get; set; }
}

具有以下架构:

If Exists(Select * from sysobjects where name = 'Sightings')
Drop Table Sightings

If Exists(Select * from sysobjects where name = 'SpaceShips')
Drop Table SpaceShips

CREATE TABLE [dbo].[SpaceShips](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DriveType] [varchar](max) NOT NULL,
CONSTRAINT [PK_SpaceShips] PRIMARY KEY CLUSTERED 
([Id] ASC) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Sightings](
[Id] [int] IDENTITY(1,1) NOT NULL,
[SpaceShipId] [int] NOT NULL,
[Lat] [decimal](18, 0) NOT NULL,
[Lon] [decimal](18, 0) NOT NULL,
CONSTRAINT [PK_Sightings] PRIMARY KEY CLUSTERED 
([Id] ASC) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Sightings]  WITH CHECK ADD CONSTRAINT [FK_Sightings_SpaceShips] FOREIGN KEY([SpaceShipId]) REFERENCES [dbo].[SpaceShips] ([Id])
GO

ALTER TABLE [dbo].[Sightings] CHECK CONSTRAINT [FK_Sightings_SpaceShips]
GO

Insert into SpaceShips (DriveType) Values ('X18-9'),('PV-276M')
Insert into Sightings (SpaceShipId, Lat, Lon) Values (1, 10, 90), (1, 20, 80), (1, 30, 70), (1, 40, 60)
Insert into Sightings (SpaceShipId, Lat, Lon) Values (2, 104, 64), (2, 105, 63), (2, 106, 62), (2, 107, 61)

我正在尝试使用 dapper 选择 SpaceShip 列表,包括它们相关的 Sightings,如下所示:

using (var con = MuzakiFactory.OpenPortal())
{
    try
    {
      var sql = @"Select * From SpaceShips ship left join Sightings s on s.SpaceShipId = ship.id";
      var result = con.Query<SpaceShip, List<Sighting>, SpaceShip>
                       (sql, (ship, sightings) => {
                                                   ship.Sightings = sightings; 
                                                   return ship;
                                                  });
      return result;
    }
    catch (Exception ex)
    {
     Captains.Log(ex);
     throw;
    }
}

但结果是 SpaceShips 列表,其中 Sightings 为空。

更新

使用 Marc 关于 QueryMultiple 的建议并自己连接似乎更容易。为了完成这项工作,我必须将 public int SpaceShipId {get;set;} 添加到我的 Sighting 类中。我最终得到了这个:

var sql = @"Select * From SpaceShips; Select * from Sightings;";
using (var multi = con.QueryMultiple(sql))
  {
   var ships = multi.Read<SpaceShip>().ToList();
   var sightings = multi.Read<Sighting>().ToList();
   foreach(var ship in ships)
   {
    ship.Sightings = new List<Sighting>(sightings.Where(x => x.SpaceShipId == ship.Id));
   }
   return ships;
  }

注意:您显然希望在每个查询的 where 子句中包含父 ID。

最佳答案

首先,您必须使用 <SpaceShip, Sighting, SpaceShip> ,并编写您自己的身份管理器(阅读:字典)以使重复的数据唯一。伪代码:

(ship, sighting) => {
    SpaceShip actualShip;
    if(!ships.TryGetValue(ship.Id, out actualShip)) {
        ships.Add(ship.Id, actualShip = ship);
    }
    actualShip.Sightings.Add(sighting);
    return actualShip;
}

哪里shipsDictionary<int, SpaceShip>或类似的。如果您认为这是常见情况,我们当然可以考虑将其作为内置选项。

但是!这可能需要很多额外的列。就我个人而言,我很想在这里考虑使用 QueryMultiple 的多结果查询。并将两者结合起来作为后处理。

关于c# - 如何使用 dapper 返回包​​含其他类型列表的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10322882/

相关文章:

c# - 通用线性分段查找表

c# - 使用 Dapper 水化复杂对象

c# - 用dapper查询oracle的集合参数

sql-server - Dapper 参数长度

c# - 从 ASP.NET 5 Web API 返回文件

c# - 网络服务代理设置

c# - 通过 Go With Exceptions 拆分 SQL 脚本

c# - Java 和 C# 和 Python 一样是 "customizable"吗?

c# - 使用 Dapper.Net 进行调试不会进入 Dapper 调用 - 未找到 SqlMapper.cs

c# - 通过存储过程将数据列表返回给 dapper