#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:
-
Использовать
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() };
Также вместо выполнения подзапроса просто используйте данные из только что выполненного соединения.
-
Лучшим вариантом, использующим 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(....) };