簡體   English   中英

如何使用dapper返回包含其他類型列表的類型?

[英]How can I use dapper to return a type that contains a list of some other type?

如何在一個查詢中使用短小精悍選擇所有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;
    }
}

但結果是一張空SightingsSpaceShips列表。

更新

使用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並將兩者結合在一起作為后處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM