繁体   English   中英

这些LINQ查询之间有什么区别?

[英]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> ,它打破了查询的“组合”; 这有两个影响:

  • 你每次都在阅读你的桌子上的所有(或者至少比你需要的更多),即使你要求一排
  • 您正在运行LINQ-to-Objects规则,因此区分大小写适用

相反,您希望在数据层中使用IQueryable<T> ,允许您根据需要将多个查询与其他WhereOrderBySkipTake等组合在一起,并使其构建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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM