C# 从LINQ生成的SQL不一致
我正在对ORACLE使用Telerik Open/Data Access ORM 为什么这两条语句会产生不同的SQL命令 声明#1C# 从LINQ生成的SQL不一致,c#,linq,plsql,telerik-open-access,C#,Linq,Plsql,Telerik Open Access,我正在对ORACLE使用Telerik Open/Data Access ORM 为什么这两条语句会产生不同的SQL命令 声明#1 IQueryable<WITransmits> query = from wiTransmits in uow.DbContext.StatusMessages select wiTransmits; query = query.Where(e=>e.MessageID == id); 声明#2 IQueryable
IQueryable<WITransmits> query = from wiTransmits in uow.DbContext.StatusMessages
select wiTransmits;
query = query.Where(e=>e.MessageID == id);
声明#2
IQueryable<WITransmits> query = from wiTransmits in uow.DbContext.StatusMessages
select new WITransmits
{
MessageID = wiTranmits.MessageID,
Name = wiTransmits.Name
};
query = query.Where(e=>e.MessageID == id);
使用第二条语句#2生成的查询返回表中的所有记录,而我只需要一条记录。数以百万计的记录使这一点成为禁忌。第一个查询返回定义的完整对象,因此任何附加限制(如
Where
)都可以在实际运行之前附加到它。因此,可以如您所示组合查询
第二个返回一个新对象,它可以是任何类型,也可以包含任何信息。因此,查询将作为“返回所有内容”发送到数据库,并且在创建对象之后,除了与Where
子句匹配的对象之外,所有对象都将被丢弃
尽管两者的类型相同,但想想这种情况:
var query = from wiTransmits in uow.DbContext.StatusMessages
select new WITransmits
{
MessageID = wiTranmits.MessageID * 4 - 2,
Name = wiTransmits.Name
};
现在如何组合Where
查询?当然,您可以在新对象创建过程中遍历代码并尝试将其移到外部,但由于可能存在任何问题,因此这是不可行的。如果检查是某种查找功能,该怎么办?如果它不是确定性的呢
因此,如果您基于数据库对象创建新对象,将有一个边界,在该边界中检索对象,然后在内存中执行进一步的查询。Telerik Data Access将尝试将每个查询拆分为数据库端和客户端(或内存LINQ,如果您愿意)。
使用
select new
进行投影肯定会触发LINQ表达式树中的所有内容在投影后转到客户端。这意味着在第二种情况下,您的LINQ查询效率低下,因为内存中应用了任何筛选,并且您已经传输了大量不必要的数据。
如果您希望以案例2中的方式编写LINQ表达式,您可以将
Select
子句追加到last,或者将结果显式转换为IEnumerable
,以使任何进一步的处理都可以在内存中完成。看起来像是ORM将投影作为IEnumerable
返回。在第一条语句之后的两种情况下,查询的类型是什么?它们都是IQueryable(更新的原始帖子)和具体类型?这不是PL/SQL问题。我想你的意思是。在一个类似ORM的实体框架中,整个表达式——包括wiTranmits.MessageID*4-2
——将被翻译成SQL,因此按MessageID
排序/过滤也将显示在查询中。我认为Telerik在这里有一个不同的策略。也许更好的检查方法是MessageID=LocalFunction(wiTransmits.MessageID),
SELECT
a."MESSAGE_ID" COL1,
-- additional fields
FROM "XFE_REP"."WI_TRANSMITS" a
var query = from wiTransmits in uow.DbContext.StatusMessages
select new WITransmits
{
MessageID = wiTranmits.MessageID * 4 - 2,
Name = wiTransmits.Name
};