Linq to sql 在LINQ中使用自定义表达式会导致每次使用都有一个查询
我有以下问题:在我们的数据库中,我们记录帮助台记录单,并在记录单下预订时间。其中包括一份访问报告。就是这样:票证=>visitreport=>hours 小时具有某种“种类”,它不是由小时记录中的类型指示器确定的,而是通过检查小时的各种属性来编译的。例如,有客户但不是服务小时的小时始终是发票小时 我最不想看到的是,这些“种类”的定义在代码中随处可见。他们一定在一个地方。其次,我希望能够从各种小时集合中计算小时总数。例如,具有特定日期和特定客户的票据的扁平集合。或标记为“解决方案”的所有注册 我决定使用“分层”数据库访问方法。同样的函数可以为屏幕显示提供数据,也可以为.pdf格式的报告提供数据。因此,第一步收集所有相关数据。它可以用于.pdf创建,也可以用于屏幕表示。在这种情况下,必须在第二步中对其进行分页和排序。这样我就不需要使用相同数据的单独查询了 数据量可能很大,就像创建年度总计一样。因此,来自第一步的数据应该是可查询的,而不是可枚举的。为了确保即使在结果中添加小时数总和时也可以查询,我创建了以下函数:Linq to sql 在LINQ中使用自定义表达式会导致每次使用都有一个查询,linq-to-sql,expression-trees,iqueryable,Linq To Sql,Expression Trees,Iqueryable,我有以下问题:在我们的数据库中,我们记录帮助台记录单,并在记录单下预订时间。其中包括一份访问报告。就是这样:票证=>visitreport=>hours 小时具有某种“种类”,它不是由小时记录中的类型指示器确定的,而是通过检查小时的各种属性来编译的。例如,有客户但不是服务小时的小时始终是发票小时 我最不想看到的是,这些“种类”的定义在代码中随处可见。他们一定在一个地方。其次,我希望能够从各种小时集合中计算小时总数。例如,具有特定日期和特定客户的票据的扁平集合。或标记为“解决方案”的所有注册 我决
public static decimal TreeHours(this IEnumerable<Uren> h, FactHourType ht)
{
IQueryable<Uren> hours = h.AsQueryable();
ParameterExpression pe = Expression.Parameter(typeof(Uren), "Uren");
Expression left = Expression.Property(pe, typeof(Uren).GetProperty("IsOsab"));
Expression right = Expression.Constant(true, typeof(Boolean));
Expression isOsab = Expression.Equal(Expression.Convert(left, typeof(Boolean)), Expression.Convert(right, typeof(Boolean)));
left = Expression.Property(pe, typeof(Uren).GetProperty("IsKlant"));
right = Expression.Constant(true, typeof(Boolean));
Expression isCustomer = Expression.Equal(Expression.Convert(left, typeof(Boolean)), Expression.Convert(right, typeof(Boolean)));
Expression notOsab;
Expression notCustomer;
Expression final;
switch (ht)
{
case FactHourType.Invoice:
notOsab = Expression.Not(isOsab);
final = Expression.And(notOsab, isCustomer);
break;
case FactHourType.NotInvoice:
notOsab = Expression.Not(isOsab);
notCustomer = Expression.Not(isCustomer);
final = Expression.And(notOsab, notCustomer);
break;
case FactHourType.OSAB:
final = Expression.And(isOsab, isCustomer);
break;
case FactHourType.OsabInvoice:
final = Expression.Equal(isCustomer, Expression.Constant(true, typeof(Boolean)));
break;
case FactHourType.Total:
final = Expression.Constant(true, typeof(Boolean));
break;
default:
throw new Exception("");
}
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { hours.ElementType },
hours.Expression,
Expression.Lambda<Func<Uren, bool>>(final, new ParameterExpression[] { pe })
);
IQueryable<Uren> result = hours.Provider.CreateQuery<Uren>(whereCallExpression);
return result.Sum(u => u.Uren1);
}
公共静态十进制树小时(此IEnumerable h,FactHourType ht)
{
IQueryable小时数=h.AsQueryable();
ParameterExpression pe=Expression.Parameter(typeof(Uren),“Uren”);
表达式left=Expression.Property(pe,typeof(Uren).GetProperty(“IsOsab”);
表达式右=表达式常数(true,typeof(Boolean));
表达式isOsab=Expression.Equal(Expression.Convert(left,typeof(Boolean)),Expression.Convert(right,typeof(Boolean));
left=Expression.Property(pe,typeof(Uren).GetProperty(“IsKlant”);
右=表达式.常量(true,typeof(Boolean));
表达式isCustomer=Expression.Equal(Expression.Convert(左,typeof(布尔)),Expression.Convert(右,typeof(布尔));
表达NOTSAB;
表达不是客户;
最终表达;
开关(ht)
{
案例FactHourType.发票:
NOTSAB=表达式Not(isOsab);
最终=表达式。和(NOTSAB,是客户);
打破
案例FactHourType.NotInvoice:
NOTSAB=表达式Not(isOsab);
notCustomer=表达式。Not(isCustomer);
最终=表达式和(非SAB,非客户);
打破
案例FactHourType.OSAB:
最终=表达式和(isOsab,是客户);
打破
case FactHourType.OsabInvoice:
final=Expression.Equal(isCustomer,Expression.Constant(true,typeof(Boolean)));
打破
案例FactHourType.总计:
final=Expression.Constant(true,typeof(Boolean));
打破
违约:
抛出新异常(“”);
}
MethodCallExpression,其中CallExpression=Expression.Call(
类型(可查询),
“哪里”,
新类型[]{hours.ElementType},
小时,表情,
表达式.Lambda(final,新参数Expression[]{pe})
);
IQueryable result=hours.Provider.CreateQuery(whereCallExpression);
返回结果.Sum(u=>u.Uren1);
}
这个函数背后的想法是,它应该保持可查询性,这样我就不会将装载的数据切换为可枚举的
我设法一直抱怨到最后。在步骤1中,我收集原始数据。在第2步中,我对数据进行排序,然后分页。在步骤3中,数据被转换为JSon并发送到客户端。这张票总共花了几个小时
问题是:我对每张票的时间有一个查询。这是数百个查询!那太多了
我尝试了以下方法:
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Ticket>(t => t.Bezoekrapport);
options.LoadWith<Bezoekrapport>(b => b.Urens);
dc.LoadOptions = options;
DataLoadOptions=newdataloadoptions();
options.LoadWith(t=>t.Bezoekrapport);
options.LoadWith(b=>b.Urens);
dc.LoadOptions=选项;
Bezoekrapport是荷兰语中“visitreport”的简单意思。当我查看检索票证的查询时,我看到它加入了Bezoekrapport/visitreport,但没有加入附加到它的小时数
我使用的第二种方法是在LINQ中手动加入小时数,但这并不奏效
我一定是做错了什么。这里最好的方法是什么
下面的代码片段是如何检索数据的。在最后一步对strHours调用toList()时,我收到了大量的查询。我已经试了两天来解决这个问题,但就是不起作用。。。我的方法或函数树小时一定有问题
步骤1:
IQueryable<RelationHoursTicketItem> HoursByTicket =
from Ticket t in allTickets
let RemarkSolved = t.TicketOpmerkings.SingleOrDefault(tr => tr.IsOplossing)
let hours = t.Bezoekrapport.Urens.
Where(h =>
(dateFrom == null || h.Datum >= dateFrom)
&& (dateTo == null || h.Datum <= dateTo)
&& h.Uren1 > 0)
select new RelationHoursTicketItem
{
Date = t.DatumCreatie,
DateSolved = RemarkSolved == null ? (DateTime?)null : RemarkSolved.Datum,
Ticket = t,
Relatie = t.Relatie,
HoursOsab = hours.TreeHours(FactHourType.OSAB),
HoursInvoice = hours.TreeHours(FactHourType.Invoice),
HoursNonInvoice = hours.TreeHours(FactHourType.NotInvoice),
HoursOsabInvoice = hours.TreeHours(FactHourType.OsabInvoice),
TicketNr = t.Id,
TicketName = t.Titel,
TicketCategorie = t.TicketCategorie,
TicketPriority = t.TicketPrioriteit,
TicketRemark = RemarkSolved
};
IQueryable小时票=
从票t到所有票
设RemarkSolved=t.TicketOpmerkings.SingleOrDefault(tr=>tr.IsOplossing)
让小时=t.Bezoekrapport.Urens。
其中(h=>
(dateFrom==null | | h.基准>=dateFrom)
&&(dateTo==null | | h.基准0)
选择new RelationHours TicketItem
{
日期=t.datumcreate,
DateSolved=RemarkSolved==null?(DateTime?)null:RemarkSolved.Datum,
票=t,
Relatie=t.Relatie,
HoursOsab=hours.TreeHours(FactHourType.OSAB),
HoursInvoice=小时数树小时数(FactHourType.Invoice),
HoursNonVoice=hours.TreeHours(FactHourType.NotInvoice),
HoursOsabInvoice=hours.TreeHours(FactHourType.OsabInvoice),
TicketNr=t.Id,
sort = sort ?? "TicketNr";
IQueryable<RelationHoursTicketItem> hoursByTicket = GetRelationHours(relation, dateFrom, dateTo, withBranches);
IOrderedQueryable<RelationHoursTicketItem> orderedResults;
if (dir == "ASC")
{
orderedResults = hoursByTicket.OrderBy(sort);
}
else
{
orderedResults = hoursByTicket.OrderByDescending(sort);
}
IEnumerable<RelationHoursTicketItem> pagedResults = orderedResults.Skip(start ?? 0).Take(limit ?? 25);
records = hoursByTicket.Count();
return pagedResults;
IEnumerable<RelationHoursTicketItem> hours = _hourReportService.GetRelationReportHours(relation, dateFrom, dateTo, metFilialen, start, limit, dir, sort, out records);
var strHours = hours.Select(h => new
{
h.TicketNr,
h.TicketName,
RelationName = h.Relatie.Naam,
h.Date,
TicketPriority = h.TicketPriority.Naam,
h.DateSolved,
TicketCategorie = h.TicketCategorie == null ? "" : h.TicketCategorie.Naam,
TicketRemark = h.TicketRemark == null ? "" : h.TicketRemark.Opmerking,
h.HoursOsab,
h.HoursInvoice,
h.HoursNonInvoice,
h.HoursOsabInvoice
});