gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:55:07 26 4
gpt4 key购买 nike

如何使用 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com