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; }
}
Run Code Online (Sandbox Code Playgroud)
使用以下架构:
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)
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
但结果是一个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;
}
Run Code Online (Sandbox Code Playgroud)
注意: 您显然希望在每个查询的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;
}
Run Code Online (Sandbox Code Playgroud)
其中ships是 aDictionary<int, SpaceShip>或类似的。如果您认为这是常见情况,那么我们当然可以将其视为内置选项。
然而!这可能需要很多额外的列。就我个人而言,我很想在这里考虑多结果查询,并将QueryMultiple两者结合在一起作为后处理。