我使用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
会返回一条记录。
有没有更有效的方法来编写这些“帮助”类型类?
谢谢!
答案 0 :(得分:7)
这可能取决于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上的查询将在数据库端执行。目前,您的方法正在撤回数据库表中的 EVERYTHING 并过滤客户端。更改声明将使您的查询转换为SQL,并且它们将更有效地运行,并且希望能够将您的邮政编码问题解决为讨价还价。
答案 1 :(得分:1)
这里真正的问题是IEnumerable<T>
的使用,它打破了查询的“组合”;这有两个影响:
相反,您希望在数据层中使用IQueryable<T>
,允许您将多个查询与其他Where
,OrderBy
,Skip
,{{1}合并根据需要使用它,并使它构建匹配的TSQL(并使用db的区分大小写规则)。
有没有更有效的方法来编写这些“帮助”类型类?
为了更高效(更少的代码进行调试,不会流式传输整个表,更好地使用身份映射来短路其他查找(通过Take
等)):
FirstOrDefault