出现这个问题的背景是,判断一批激活码在系统中是否已经存在,很傻的一个作法是,把这一批激活码,以in(in ('ddd','aaa'))的形式来处理,导致问题的出现。
后来,查找资料,http://bbs.csdn.net/topics/350137806
在这里讨论的结果是:
你的问题不是你不会使用LINQ中的in语句,而是你传递给in语句的参数太多了。
长度可能超过2100个,甚至上万。这多恐怖呀?要知道这些内容最后就会包含在所生成的SQL语句中。
这参数也确实太长太长了。
传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。
从这个异常信息就可以知道这不是LINQ的问题。
解决办法很简单,只要将调用数据源的AsEnumerable()运算符就可以了。如下面的代码:
NorthwindDataContext db = new NorthwindDataContext(@"C:\LINQ\Northwind.mdf"); string[] CustomerIDs = { "ALFKI", "ANATR", "ANTON" }; var PartialCustomers = from CustomerObject in db.Customers.AsEnumerable() where CustomerIDs.Contains(CustomerObject.CustomerID) select CustomerObject; foreach (var CustomerObject in PartialCustomers) { Console.WriteLine(CustomerObject.CustomerID); }
上面的代码指定的数据源是db.Customers.AsEnumerable()。
从上面的讨论结果,可以得到,使用AsEnumerable()延迟加载会使问题得到解决。
那我现在的做法是:从数据库里,把所有的激活码都查出来,保存在一个List<String>里面,两个list进行比较,看是否有重复的存在。
在写LINQ语句的时候,往往会看到.AsEnumerable() 和 .AsQueryable() 。
例如:
string strcon = "Data Source=.\\SQLEXPRESS;Initial Catalog=Db_Example;Persist Security Info=True;User ID=sa;Password=sa"; SqlConnection con = new SqlConnection(strcon); con.Open(); string strsql = "select * from SC,Course where SC.Cno=Course.Cno"; SqlDataAdapter da = new SqlDataAdapter(strsql,con); DataSet ds = new DataSet(); da.Fill(ds, "mytable"); DataTable tables=ds.Tables["mytable"]; //创建表 var dslp = from d in tables.AsEnumerable() select d;//执行LINQ语句,这里的.AsEnumerable()是延迟发生,不会立即执行,实际上什么都没有发生 foreach(var res in dslp) { Response.Write(res.Field<string>("Cname").ToString()); }
上述代码使用LINQ 针对数据集中的数据进行筛选和整理,同样能够以一种面向对象的思想进行数据集中数据的筛选。在使用LINQ 进行数据集操作时,LINQ 不能直接从数据集对象中查询,因为数据集对象不支持LINQ 查询,所以需要使用AsEnumerable 方法返回一个泛型的对象以支持LINQ 的查询操作。
.AsEnumerable()是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First, Single, ToList....的时候)才执行。
下面就是.AsEnumerable()与相对应的.AsQueryable()的区别:
AsEnumerable将一个序列向上转换为一个IEnumerable, 强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。
AsQueryable将一个序列向下转换为一个IQueryable, 它生成了一个本地查询的IQueryable包装。