簡體   English   中英

如何將復雜的linq映射到對象

[英]How to map complex linq to object

尋找Ef Core和Linq的一些幫助。 讓我們說我要求收到所有支持票,包括產品,公司等信息。 這很簡單,加入的東西:

select * 
from Tickets T
left join Products P on T.ProductId = P.Id                  
left join ProductVersions PV on T.ProductVersionId = PV.Id  
left join TicketTypes TT on T.TicketTypeId = TT.Id          
left join TicketPriorities TP on T.TicketPriorityId = TP.Id 
left join TicketStates TS on T.TicketStateId = TS.Id    

left join AbpTenants A on T.TenantId = A.Id                 
    left join AbpEditions E on A.EditionId = E.Id   

left join TicketLinkedUsers TLU on TLU.TicketId = T.Id      
    left join TicketLinkTypes TLT on TLT.Id = TLU.TicketLinkTypeId  

但是我有最后4個連接的問題。

在項目中,我正在使用Ef Core。 這就是我(部分)的方式:

var query = (from o in filteredTickets
                     join o1 in _productRepository.GetAll() on o.ProductId equals o1.Id into j1
                     from s1 in j1.DefaultIfEmpty()
                     join o2 in _productVersionRepository.GetAll() on o.ProductVersionId equals o2.Id into j2
                     from s2 in j2.DefaultIfEmpty()
                     join o3 in _ticketTypeRepository.GetAll() on o.TicketTypeId equals o3.Id into j3
                     from s3 in j3.DefaultIfEmpty()
                     join o4 in _ticketPriorityRepository.GetAll() on o.TicketPriorityId equals o4.Id into j4
                     from s4 in j4.DefaultIfEmpty()
                     join o5 in _ticketStateRepository.GetAll() on o.TicketStateId equals o5.Id into j5
                     from s5 in j5.DefaultIfEmpty()
                     join o6 in _tenantManager.Tenants on o.TenantId equals o6.Id into j6
                     from s6 in j6.DefaultIfEmpty()
                     // join o7 in _editionaRepository.GetAll() on s6.EditionId equals o7.Id into j7
                     // from s7 in j7.DefaultIfEmpty()
                     // join o8 in _ticketLinkedUsersRepository.GetAll() on o.Id equals o8.TicketId into j8
                     // from s8 in j8.DefaultIfEmpty()
                     // join o9 in _ticketLinkTypesRepository.GetAll() on s9.TicketLinkTypeId equals o9.Id into j9
                     // from s9 in j9.DefaultIfEmpty()
                     select new GetTicketForView() { Ticket = ObjectMapper.Map<TicketDto>(o)
                        , ProductName = s1 == null ? "" : s1.Name.ToString()
                        , ProductVersionName = s2 == null ? "" : s2.Name.ToString()
                        , TicketTypeName = s3 == null ? "" : s3.Name.ToString()
                        , TicketPriorityName = s4 == null ? "" : s4.Name.ToString()
                        , TicketState = ObjectMapper.Map<TicketStateTableDto>(s5)
                        , Tenant = ObjectMapper.Map<TenantShortInfoDto>(s6)
                     })

要接收數據,我正在使用存儲庫模式。 然后使用AutoMapper將所有數據映射到ViewModel。 這就是我的ViewModel的樣子:

public class GetTicketForView
{
    public TicketDto Ticket { get; set; }

    public TenantShortInfoDto Tenant { get; set; }

    public string ProductName { get; set;}

    public string ProductVersionName { get; set;}

    public TicketStateTableDto TicketState { get; set; }

    public string TicketTypeName { get; set;}

    public string TicketPriorityName { get; set;}

    public List<TicketLinkedUserDto> LinkedUsers { get; set; }
}

現在,我嘗試使用TicketLinkType信息獲取有關公司(AbpTenants)的信息,其中包含有關版本(一對多關系)和TicketLinkedUsers列表(多對多關系)的信息。 架構: 在此輸入圖像描述

我可以使用其他連接接收所有必需的數據,但是我不知道如何正確綁定數據並將數據映射到GetTicketForView。 具有嵌套映射版本的LinkedUser和Tenant列表是一個問題。 現在我正在為每張票做單獨的請求以進行多對多的工作:

// execute to get tickets
tickets = await query
           .OrderBy(input.Sorting ?? "ticket.id asc")
           .PageBy(input)
           .ToListAsync();

// then for each ticket get related users:
foreach (var ticket in tickets)
{
    var linkedUsers = _ticketLinkedUsersRepository
   .GetAllIncluding(lu => lu.TicketLinkType, lu => lu.User)
   .OrderBy(a => a.TicketLinkType.Ordinal)
   .Where(p => p.TicketId == ticket.Ticket.Id).ToList();

   ticket.LinkedUsers = ObjectMapper.Map<List<TicketLinkedUserDto>>(linkedUsers);
}

這是一個非常耗時的原因,因為我可以使用o8和09在一個請求中獲取所有數據,但我為每個票證提出了額外的請求。 沒有足夠的經驗來做對。

所以問題是,如何使用linq實現第一個請求並將其映射到ViewModel。 我應該使用額外的請求嗎? 或者最好使用Ef Core Api來提出復雜的請求? 或者不可能在linq中映射復雜的東西?

提前致謝

按照提示,我重寫了一切

查詢:

var query = filteredTickets // IQueryable<Ticket>
             .Include(ten => ten.Tenant)
                .ThenInclude(ed => ed.Edition)
             .Include(p => p.Product)
             .Include(pv => pv.ProductVersion)
             .Include(tt => tt.TicketType)
             .Include(tp => tp.TicketPriority)
             .Include(ts => ts.TicketState)
             .Include(lu => lu.LinkedUsers)
                .ThenInclude(tlt => tlt.TicketLinkType)
             .Include(lu => lu.LinkedUsers)
                .ThenInclude(u => u.User)
            .ProjectTo<GetTicketForView>();

映射:

configuration.CreateMap<Ticket, TicketDto>();
configuration.CreateMap<Tenant, TenantShortInfoDto>();
configuration.CreateMap<TicketState, TicketStateTableDto>();
configuration.CreateMap<TicketLinkedUser, TicketLinkedUserDto>();

configuration.CreateMap<Ticket, GetTicketForView>()
            .ForMember(dest => dest.Ticket, conf => conf.MapFrom(src => src)
);

如果我想在將來切換到nhibernate,不確定我是否在這里失去了一些靈活性,但它比以前更好用。

暫無
暫無

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

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