[英]What's the difference between these LINQ queries?
我使用LINQ-SQL作为我的DAL,然后我有一个名为DB的项目,它充当我的BLL。 然后,各种应用程序访问BLL以从SQL数据库读取/写入数据。
我在我的BLL中为一个特定的表有这些方法:
public IEnumerable<SystemSalesTaxList> Get_SystemSalesTaxList()
{
return from s in db.SystemSalesTaxLists
select s;
}
public SystemSalesTaxList Get_SystemSalesTaxList(string strSalesTaxID)
{
return Get_SystemSalesTaxList().Where(s => s.SalesTaxID == strSalesTaxID).FirstOrDefault();
}
public SystemSalesTaxList Get_SystemSalesTaxListByZipCode(string strZipCode)
{
return Get_SystemSalesTaxList().Where(s => s.ZipCode == strZipCode).FirstOrDefault();
}
一切都很直接,我想。
Get_SystemSalesTaxListByZipCode
总是返回一个空值,即使它具有该表中存在的邮政编码。
如果我写这样的方法,它返回我想要的行:
public SystemSalesTaxList Get_SystemSalesTaxListByZipCode(string strZipCode)
{
var salesTax = from s in db.SystemSalesTaxLists
where s.ZipCode == strZipCode
select s;
return salesTax.FirstOrDefault();
}
为什么其他方法不返回相同,因为查询应该相同?
请注意,重载的Get_SystemSalesTaxList(string strSalesTaxID)
在我给它一个有效的SalesTaxID
时返回一条记录就好了。
有没有更有效的方法来编写这些“帮助”类型类?
谢谢!
这可能取决于LINQ处理IEnumerable<T>
和IQueryable<T>
的不同方式。
您已将Get_SystemSalesTaxList
声明为返回IEnumerable<SystemSalesTaxList>
。 这意味着,在第一个代码示例中,将Where运算符应用于Get_SystemSalesTaxList的结果时,它将被解析为Enumerable.Where
扩展方法。 (请注意,重要的是声明的类型。是的,在运行时Get_SystemSalesTaxList返回IQueryable<SystemSalesTaxList>
,但其声明的类型 - 编译器看到的 - 是IEnumerable<SystemSalesTaxList>
。) Enumerable.Where
运行指定的.NET对目标序列的谓词。 在这种情况下,它迭代Get_SystemSalesTaxList返回的所有SystemSalesTaxList对象,产生ZipCode属性等于指定的邮政编码字符串的那些(使用.NET String ==
运算符)。
但是在上一个代码示例中,您将Where运算符应用于db.SystemSalesTaxList
,它被声明为IQueryable<SystemSalesTaxList>
类型。 因此,该示例中的Where运算符被解析为Queryable.Where
,它将指定的谓词表达式转换为SQL并在数据库上运行它。
那么邮政编码方法的不同之处在于,第一个在.NET中运行C# s.ZipCode == strZipCode
测试,第二个将其转换为SQL查询WHERE ZipCode = 'CA 12345'
(参数化SQL确实但你得到了这个想法)。 为什么这些会产生不同的结果? 很难确定,但C# ==
谓词区分大小写,并且根据您的排序规则设置,SQL可能区分大小写,也可能不区分大小写。 所以我怀疑strZipCode
与数据库邮政编码的情况不符,但在第二版中,SQL Server整理正在平滑这一点。
最好的解决方案可能是更改Get_SystemSalesTaxList的声明以返回IQueryable<SystemSalesTaxList>
。 这样做的主要好处是它意味着构建在Get_SystemSalesTaxList上的查询将在数据库端执行。 此刻,你的方法被拉回在数据库表中的一切 ,对其进行筛选客户端。 更改声明将使您的查询转换为SQL,并且它们将更有效地运行,并且希望能够将您的邮政编码问题解决为讨价还价。
这里真正的问题是使用IEnumerable<T>
,它打破了查询的“组合”; 这有两个影响:
相反,您希望在数据层中使用IQueryable<T>
,允许您根据需要将多个查询与其他Where
, OrderBy
, Skip
, Take
等组合在一起,并使其构建TSQL以匹配(并使用您的db的情况 -敏感性规则)。
有没有更有效的方法来编写这些“帮助”类型类?
为了更有效(更少的代码进行调试,不会流式传输整个表,更好地使用身份映射来短路其他查找(通过FirstOrDefault
等)):
public IEnumerable<SystemSalesTaxList> Get_SystemSalesTaxList()
{
return db.SystemSalesTaxLists;
}
public SystemSalesTaxList Get_SystemSalesTaxList(string salesTaxID)
{
return db.SystemSalesTaxLists.FirstOrDefault(s => s.SalesTaxID==salesTaxID);
}
public SystemSalesTaxList Get_SystemSalesTaxListByZipCode(string zipCode)
{
return db.SystemSalesTaxLists.FirstOrDefault(s => s.ZipCode == zipCode);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.