Объединение с внутренним списком

#c# #entity-framework #linq #linq-to-entities

#c# #entity-framework #linq #linq-to-entities

Вопрос:

У меня есть этот запрос linq:

 var investorData = from investor in db.Investors
                        join investorLine in db.InvestorStatementLines
                            on investor.InvestorID equals investorLine.InvestorID
                        where investor.UserId == userId
                        select new InvestorViewModel()
                        {
                            InvestorId = investor.InvestorID,
                            InvestorName = investor.Name,
                            FundingDate = investor.FundingDate,
                            DueDate = investor.DueDate,
                            FundsCommitted = investor.FundsCommitted,
                            FundsInvested = investor.FundsInvested,
                            StatementLines =
                                db.InvestorStatementLines.Where(s => s.InvestorID == investor.InvestorID)
                                    .Select(t => new InvestorStatementLineVM
                                    {
                                        Balance = t.Balance,
                                        Credit = t.Credit,
                                        Debit = t.Debit,
                                        InvestorStatementLineDetails = t.Details,
                                        Date = t.Date
                                    }).ToList()
                        };
  

Viewmodel:

 public class InvestorViewModel
{
    public int InvestorId { get; set; }
    public string InvestorName { get; set; }
    public DateTime FundingDate { get; set; }
    public DateTime? DueDate { get; set; }
    public Decimal? FundsCommitted { get; set; }
    public Decimal? FundsInvested { get; set; }
    public List<InvestorStatementLineVM>  StatementLines { get; set; }
}
  

Что происходит, когда я выполняю запрос, я получаю 125 записей, и это количество строк StatementLines для этого инвестора. Итак, я получаю 125 одинаковых записей, но я ожидаю одного результата, который будет содержать 125 строк инструкций во внутреннем списке.

Корректен ли этот запрос?

Комментарии:

1. Почему вы выполняете объединение, а затем подзапрос, чтобы в основном получить одни и те же данные? Либо удалите объединение, либо выполните группировку и удалите внутренний запрос. Или, что еще лучше, используйте вместо этого свойства навигации coding.abel.nu/2012/06/dont-use-linqs-join-navigate

2. @juharr как бы вы повторили этот запрос со свойствами навигации, не могли бы вы указать это в ответе? Спасибо

3. Какой «один результат» вы хотите получить? Первый оператор, последний, количество всех операторов или что-то еще?

4. Кстати, это L2E или Linq для сущностей, а не Linq для SQL или Linq для объектов.

Ответ №1:

Вот как вы можете сделать это с помощью свойств навигации

 var investorData = from investor in db.Investors
                   where investor.UserId == userId
                   select new InvestorViewModel()
                   {
                       InvestorId = investor.InvestorID,
                       InvestorName = investor.Name,
                       FundingDate = investor.FundingDate,
                       DueDate = investor.DueDate,
                       FundsCommitted = investor.FundsCommitted,
                       FundsInvested = investor.FundsInvested,
                       StatementLines = investor.InvestorStatementLines
                           .Select(t => new InvestorStatementLineVM
                           {
                               Balance = t.Balance,
                               Credit = t.Credit,
                               Debit = t.Debit,
                               InvestorStatementLineDetails = t.Details,
                               Date = t.Date
                           }).ToList()
                   };
  

Ответ №2:

  1. Использовать GroupJoin вместо объединения: ( _join x in y on x.a equals y.a
    into z_
    )

     var investorData = from investor in db.Investors
                            join investorLine in db.InvestorStatementLines
                            on investor.InvestorID equals investorLine.InvestorID
                            into investorLine
                            where investor.UserId == userId
    
                            select new InvestorViewModel()
                            {
                                InvestorId = investor.InvestorID,
                                InvestorName = investor.Name,
                                FundingDate = investor.FundingDate,
                                DueDate = investor.DueDate,
                                FundsCommitted = investor.FundsCommitted,
                                FundsInvested = investor.FundsInvested,
                                StatementLines = investorLine
                                    .Select(t => new InvestorStatementLineVM
                                    {
                                        Balance = t.Balance,
                                        Credit = t.Credit,
                                        Debit = t.Debit,
                                        InvestorStatementLineDetails = t.Details,
                                        Date = t.Date
                                    }).ToList()
                            };
      

    Также вместо выполнения подзапроса просто используйте данные из только что выполненного соединения.

  2. Лучшим вариантом, использующим entity framework, является использование свойств навигации, и тогда вам не нужно выполнять объединение, а просто иметь InvestorStatementLines в качестве своего свойства investor .

    Чтобы задать свойства навигации:

     public class InvestorViewModel
    {
        public int InvestorId { get; set; }
        public string InvestorName { get; set; }
        public DateTime FundingDate { get; set; }
        public DateTime? DueDate { get; set; }
        public Decimal? FundsCommitted { get; set; }
        public Decimal? FundsInvested { get; set; }
        public virtual ICollection<InvestorStatementLineVM>  StatementLines { get; set; }
    }
      

    И запрос будет таким же простым, как:

     var investorData = from investor in db.Investors
                       where investor.UserId == userId
                       select new InvestorViewModel()
                       {
                           InvestorId = investor.InvestorID,
                           ....
                           StatementLines = investor.InvestorStatementLines.Select(....)
                       };