簡體   English   中英

EF 6.1 Database.SqlQuery投影到復雜類型(多對多關系)

[英]EF 6.1 Database.SqlQuery projection into complex type (many-to-many relationship)

在Entity Framework 6.1中是否可以使用Database.SqlQuery命令執行包含多對多關系的查詢,並將其映射回DTO(使用中間DTO-我知道這不可能一次完成)? 以及該動作將如何執行?

此示例是我當前面臨的問題的極其簡化的版本 我只是對Database.SqlQuery可以(不能)完成什么感興趣。

我知道我可以使用導航屬性(使用Linq),但是我正在研究更復雜的查詢的性能。 這只是我要達到的目標的非常簡化的版本。

數據庫

在此處輸入圖片說明

DTO

 public class EventDto{

      public int EventId {get;set;}
      public string Name {get;set;}
      public string Slug {get;set;}

      public List<ArtistDto> Headliners {get;set;}
 }

 public class ArtistDto{

      public int ArtistId {get;set;}
      public string Name {get;set;}
      public string Bio {get;set;}
 }

臨時DTO

public class EventWithHeadlinersDto{

      public int EventId {get;set;}
      public string Name {get;set;}
      public string Slug {get;set;}

      public int ArtistId {get;set;}
      public string Name {get;set;}
      public string Bio {get;set;}
 }

 return Context.Database.SqlQuery<EventWithHeadlinersDto>(@"
                                SELECT * FROM [Events] E
                                LEFT JOIN [Headliners] H ON E.EventId = H.EventId
                                LEFT JOIN [Artists] A ON H.ArtistId = A.ArtistId
                                WHERE E.eventid = @eventId",
                               new SqlParameter("eventId", eventId))
                               .ToListAsync();

需要一些編碼(基本上是復制EF查詢實現過程),但是可行。

首先,應將臨時DTO修改為包括所有必填字段,並考慮到left joins (在需要時使用nullable類型):

public class EventWithHeadlinersDto
{
    // Event Info
    public int EventId { get; set; }
    public string EventName { get; set; }
    public string EventSlug { get; set; }
    // Artist Info
    public int? ArtistId { get; set; }
    public string ArtistName { get; set; }
    public string ArtistBio { get; set; }
}

然后,您應確保SQL SELECT包括所有必要的列,並在必要時使用別名以匹配DTO屬性名稱:

var sql = @"
    SELECT
       E.EventId, E.Name EventName, E.Slug EventSlug,
       A.ArtistId, A.Name ArtistName, A.Bio ArtistBio
    FROM [Events] E
    LEFT JOIN [Headliners] H ON E.EventId = H.EventId
    LEFT JOIN [Artists] A ON H.ArtistId = A.ArtistId
    WHERE E.EventId = @eventId";

然后執行sql查詢並獲得設置的DTO結果:

var dataSet = await query.ToListAsync();

最后將其轉換為所需的格式:

var eventMap = new Dictionary<int, EventDto>();
var artistMap = new Dictionary<int, ArtistDto>();
foreach (var entry in dataSet)
{
    EventDto @event;
    if (!eventMap.TryGetValue(entry.EventId, out @event))
    {
        @event = new EventDto
        {
            EventId = entry.EventId, 
            Name = entry.EventName,
            Slug = entry.EventSlug,
            Headliners = new List<ArtistDto>()
        };
        eventMap.Add(@event.EventId, @event);
    }
    if (entry.ArtistId != null)
    {
        ArtistDto artist;
        if (!artistMap.TryGetValue(entry.ArtistId.Value, out artist))
        {
            artist = new ArtistDto
            {
                ArtistId = entry.ArtistId.Value,
                Name = entry.ArtistName,
                Bio = entry.ArtistBio,
            };
            artistMap.Add(artist.ArtistId, artist);
        }
        @event.Headliners.Add(artist);
    }
}
var resultSet = eventMap.Values.ToList();

當然,在示例情況下,結果集將僅包含0或1個項目,但是以上內容適用於任何應用的過濾。

暫無
暫無

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

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