我遇到LINQ查询问题而且不知道如何解决它:/
我有两张桌子。一个是属性,第二个是属性行,但是我需要从行中总结几个小时并将其转换为属性;无法解释它;)这是我试图创建的查询:
var query = (from ta in session.db.TimesheetAttributes
join tr in session.db.TimesheetRows on ta.Id equals tr.TimesheetAttributesId into tempTR
from ttr in tempTR.DefaultIfEmpty()
group ttr by new { ta.TimesheetId, ta.Date, ta.SickNote, ta.Vacation, ta.OccasionVacation } into g
select new
{
Id = g.Key.TimesheetId,
Date = g.Key.Date,
WeekDay = g.Key.Date.ToString("dddd", new CultureInfo("pl-PL")),
Description = String.Format("{0:dd/MM/yyyy}", g.Key.Date),
SickNote = g.Key.SickNote,
Vacation = g.Key.Vacation,
OccasionVacation = g.Key.OccasionVacation,
Hours = String.Format("{0:HH:mm}", (new DateTime(g.Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal + (t.DateTo - t.DateFrom)).Ticks)))
}).OrderBy(c=>c.Date).ToList();
问题在于并非每个属性都有行,这就是我尝试使用DefaultIfEmpty()的原因,但是这个查询无效:(
我的旧查询正在运行,但是我的ORM为每一行创建了一个新查询,因此,如果我有1000个TimesheetAttributes,则会选择1000:/
这是我的旧查询:
var query = (from c in session.db.TimesheetAttributes
where ((c.Active == true)
&& (c.Timesheet.Active == true)
&& (c.ValidFrom <= validDate)
&& (c.ValidTo > validDate)
&& (c.Timesheet.ContactPersonId == session.ContactPersonAttributes.ContactPersonId))
select new
{
Id = c.TimesheetId,
c.Date,
WeekDay = c.Date.ToString("dddd", new CultureInfo("pl-PL")),
Description = String.Format("{0:dd/MM/yyyy}", c.Date),
Hours = String.Format("{0:HH:mm}", (new DateTime((c.TimesheetRows.Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal + (t.DateTo - t.DateFrom)).Ticks)))),
c.SickNote,
c.Vacation,
c.OccasionVacation
}).OrderBy(c => c.Date).ToList();
编辑:
这是我得到的异常:&#34;调用的目标抛出了异常&#34; InnerException:&#34;对象引用未设置为对象的实例&#34;
答案 0 :(得分:0)
您使用旧查询时遇到的问题通常被称为n+1 problem。
您应该能够调整原始查询,如下所示:
var query = (from c in session.db.TimesheetAttributes
from cr in c.TimesheetRows
where ((c.Active == true)
&& (c.Timesheet.Active == true)
&& (c.ValidFrom <= validDate)
&& (c.ValidTo > validDate)
&& (c.Timesheet.ContactPersonId == session.ContactPersonAttributes.ContactPersonId))
select new
{
Id = c.TimesheetId,
c.Date,
WeekDay = c.Date.ToString("dddd", new CultureInfo("pl-PL")),
Description = String.Format("{0:dd/MM/yyyy}", c.Date),
Hours = String.Format("{0:HH:mm}", (new DateTime((cr.Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal + (t.DateTo - t.DateFrom)).Ticks)))),
c.SickNote,
c.Vacation,
c.OccasionVacation
}).OrderBy(c => c.Date).ToList();
如果仍然发出声音,您可以尝试在Ten属性中添加一个tenary运算符......
Hours = String.Format("{0:HH:mm}", !(cr == null) && cr.Any() ? (new DateTime((cr.Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal + (t.DateTo - t.DateFrom)).Ticks))) : DateTime.MinValue
编辑:
我明白你的意思,我的脑子还没有醒来。您遇到的问题是底层查询提供程序没有注意到它需要获取TimesheetAttributes和关联/相关的TimesheetRows。这可能是因为TimesheetRows深埋在生成您正在选择的匿名类型的表达式中。
我的查询语法并不精彩(我更喜欢在lambda中这样做 - 我觉得它更像未来证明但这只是一种感觉),但我会试一试......
var query = (from res in
(from c in session.db.TimesheetAttributes
where ((c.Active == true)
&& (c.Timesheet.Active == true)
&& (c.ValidFrom <= validDate)
&& (c.ValidTo > validDate)
&& (c.Timesheet.ContactPersonId == session.ContactPersonAttributes.ContactPersonId))
select new
{
c = c,
cr = c.TimesheetRows
})
select new
{
Id = c.TimesheetId,
c.Date,
WeekDay = c.Date.ToString("dddd", new CultureInfo("pl-PL")),
Description = String.Format("{0:dd/MM/yyyy}", c.Date),
Hours = String.Format("{0:HH:mm}", (new DateTime((cr.Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal + (t.DateTo - t.DateFrom)).Ticks)))),
c.SickNote,
c.Vacation,
c.OccasionVacation
}).OrderBy(c => c.Date).ToList();
它看起来比原版更丑,我确信有更好的方法,但它应该使表达式足够清楚,以便您的查询提供程序(L2S或其他)实现它需要返回两个实体,并且避免n + 1问题。