当我运行此代码时:
return dbAccess.ExecuteDataTable(dbAccess)
.AsEnumerable()
.Select(r => r.Field<int>("Id"))
.ToList();
它给了我一个错误:
SqlParameter已经在SqlParameterCollection
中
虽然我知道AsEnumerable可以在延迟执行或延迟加载这个概念上运行,但是这个概念仍然没有在我脑海中占据一席之地。
任何人都可以解释一下AsEnumerable和这段代码的工作原理吗?
答案 0 :(得分:0)
您的代码等效于以下
var retVal = new List<int>();
var dataTable = dbAccess.ExecuteDataTable(dbAccess);
foreach(DataRow r in dataTable.Rows)
{
var rowResult = (int)r["Id"]; //`(int)r["Id"]` is equivalent to `r.Field<int>("Id")`
retVal.Add(rowResult);
}
return retVal;
您不必担心代码的执行不同,因为您在最后放置.ToList()
,因此它会在您向我们展示的位置运行代码。如果你把它排除在外,那么在不使用yield return
的情况下显示“等效代码”会更加困难,而这可能让你更加困惑。
上面说的是,上面代码中唯一可以抛出我看到的错误的是dbAccess.ExecuteDataTable(dbAccess);
。尝试重写上面的代码,看看你的错误发生在哪一行,也许它会给你指明下一步的方向。
答案 1 :(得分:0)
AsEnumerable只是将对象强制转换为IEnumerable(来自 IQeuriable),这意味着您将使用的任何LINQ运算符 为该接口声明的运算符(IEnumerable)。
这意味着不要将运算符转换为SQL,而是让它 服务器处理它,整个表将枚举(从中检索) DB),然后在内存中进行操作。
正如@Scott Chamberlain所提到的,我所回答的内容与您的代码无关,因为它使用的是DataTable,而不是IQueriable
。
AsEnumerable
只为DataTable
创建可枚举的包装器,一次检索每一行,并允许您在DataTable
上使用LINQ。这与例外无关。
另一件事,调用ToList
强制执行查询,因此不会延迟执行。
要回答关于异常的问题,如果您提供向查询添加参数的代码,将会很有帮助。