我的LINQ语句中有这个错误,但是我不明白它的问题或者我该如何解决它:
这是我的LINQ:
int year = 2016;
int month = 11;
DateTime dateFrom = new DateTime(year, month, 1);
DateTime dateTo = dateFrom.AddMonths(1);
int daysInMonth = DateTime.DaysInMonth(year, month);
var data = db_pdv.Pdv.Where(x => x.Fecha >= dateFrom && x.Fecha < dateTo);
var model_pdv = data.GroupBy(x => new { Pdv = x.Clave_PDV, Nombre_Pdv = x.Nombre_Pdv, Turno = x.Turno, Nombre_Turno = x.Nombre_Turno, Pla_ID = x.Platillo, Nombre_Platillo = x.Nombre_Platillo, Precio = x.Precio })
.Select(x => new DishVM()
{
Clave_PDV = x.Key.Pdv,
Nombre_Pdv = x.Key.Nombre_Pdv,
Turno = x.Key.Turno,
Nombre_Turno = x.Key.Nombre_Turno,
Platillo = x.Key.Pla_ID,
Nombre_Platillo = x.Key.Nombre_Platillo,
Precio = x.Key.Precio,
Days = new List<int>(new int[daysInMonth]),
Data = x
}).ToList();
这是我的“DishVM”CLass
public class DishVM
{
public string Clave_PDV { get; set; }
public string Nombre_Pdv { get; set; }
public string Turno { get; set; }
public string Nombre_Turno { get; set; }
public int Platillo { get; set; }
public string Nombre_Platillo { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
public decimal Precio { get; set; }
public List<int> Days { get; set; }
[Display(Name = "Quantity")]
public int TotalQuantity { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
[Display(Name = "Total")]
public decimal TotalPrice { get; set; }
public IEnumerable<Pdv> Data { get; set; }
}
我该如何解决这个问题? 提前致谢
答案 0 :(得分:3)
我该如何解决这个问题?
首先要知道问题所在。
在Entity Framework中,任何在DbSet
上运行的表达式(如db_pdv.Pdv
)都会被转换为SQL。 整个表达式。在您的情况下,此“整个表达式”为model_pdv
,其结构为db_pdv.Pdv.Where(...).GroupBy(...).Select()
。表达式包含new List<int>(new int[daysInMonth])
。你会明白把它翻译成SQL是不可能的;数据库引擎如何知道如何构造.Net List<T>
对象?
那么如何解决呢?
您可以首先构建列表,然后构建表达式:
...
var daysList = new List<int>(new int[daysInMonth]);
var data = db_pdv.Pdv.Where(...
...
Precio = x.Key.Precio,
Days = daysList,
Data = x
现在,您已将SQL转换任务简化为将原始值(整数)转换为SQL。 EF非常清楚如何做到这一点。但结果是......好笑。如果检查生成的SQL,则会看到EF将整数列表转换为某种SQL表。看起来像......
CROSS JOIN (SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]
UNION ALL
SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]
UNION ALL
...
...等等。
这里发生的事情基本上是在c#中构建一个列表,将其转换为SQL构造,让数据库构造一个结果集,将结果集转换为c#中的列表 - 复杂。
另一种选择是在内存中运行整个语句:
var data = db_pdv.Pdv.Where(x => x.Fecha >= dateFrom && x.Fecha < dateTo)
.AsEnumerable();
var model_pdv = ...
通常情况下,由于here解释的原因,我不主张采用这种方法。但在这种情况下它会没问题,因为最终你将使用所有数据(Data = x
),因此你不会从数据库中获取超过你需要的数据。
更深刻的解决方案是从视图模型中完全删除列表。冗余是不一致的母亲。为什么所有模型实例都需要相同的整数列表?您应该只能在需要它的位置构建一次列表来显示UI。