Whether to use AsEnumerable() in LINQ or not?
我知道
有人能提出更好的方法吗?
这是一些我要做的代码示例?
使用AsEnumerable():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var Data = (from r in _context.PRD_ChemProdReq.AsEnumerable() //where r.RecordStatus =="NCF" orderby r.RequisitionNo descending select new PRDChemProdReq { RequisitionID = r.RequisitionID, RequisitionNo = r.RequisitionNo, RequisitionCategory = DalCommon.ReturnRequisitionCategory(r.RequisitionCategory), RequisitionType = DalCommon.ReturnOrderType(r.RequisitionType), ReqRaisedOn = (Convert.ToDateTime(r.ReqRaisedOn)).ToString("dd'/'MM'/'yyyy"), RecordStatus= DalCommon.ReturnRecordStatus(r.RecordStatus), RequisitionFromName = DalCommon.GetStoreName(r.RequisitionFrom), RequisitionToName = DalCommon.GetStoreName(r.RequisitionTo) }).ToList(); |
没有aseNumerable():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var Data = (from r in _context.PRD_ChemProdReq //where r.RecordStatus =="NCF" orderby r.RequisitionNo descending select new PRDChemProdReq { RequisitionID = r.RequisitionID, RequisitionNo = r.RequisitionNo, RequisitionCategory = r.RequisitionCategory, RequisitionType = (r.RequisitionType), ReqRaisedOnTemp = (r.ReqRaisedOn), RecordStatus= (r.RecordStatus), RequisitionFrom = (r.RequisitionFrom), RequisitionTo = (r.RequisitionTo) }).ToList(); foreach (var item in Data) { item.RequisitionCategory = DalCommon.ReturnRequisitionCategory(item.RequisitionCategory); item.RequisitionType = DalCommon.ReturnOrderType(item.RequisitionType); item.ReqRaisedOn = (Convert.ToDateTime(item.ReqRaisedOnTemp)).ToString("dd'/'MM'/'yyyy"); item.RecordStatus = DalCommon.ReturnRecordStatus(item.RecordStatus); item.RequisitionFromName = DalCommon.GetStoreName(item.RequisitionFrom); item.RequisitionToName = DalCommon.GetStoreName(item.RequisitionTo); } |
看起来您将这两个接口混淆为两个完全不同的东西。事实上,
尽管这些接口的实现方式非常不同,但在幕后,IEnumerable将在内存中处理您的集合,而iQueryable将把查询传递给基础数据提供程序。您可以想象,如果一个数据库表包含数百万条记录,并且您试图对其进行排序,那么DBServer可以非常快速地进行排序(使用索引),这样Queryable就会发光。对于IEnumerable,所有数据都需要加载到计算机内存中并在那里排序。
要获得更长的答案,请搜索"IEnumerable IQueryable Difference",这样,您将看到许多详细信息:
随机链接1随机链接2
更新:如果从第二个示例中删除调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var Data = (from r in _context.PRD_ChemProdReq orderby r.RequisitionNo descending select new PRDChemProdReq { // do your initialization }); var subsetOfData = Data.Take(100).ToList(); // Now it's loaded to memory foreach (var item in subsetOfData) { item.RequisitionCategory = DalCommon.ReturnRequisitionCategory(item.RequisitionCategory); item.RequisitionType = DalCommon.ReturnOrderType(item.RequisitionType); item.ReqRaisedOn = (Convert.ToDateTime(item.ReqRaisedOnTemp)).ToString("dd'/'MM'/'yyyy"); item.RecordStatus = DalCommon.ReturnRecordStatus(item.RecordStatus); item.RequisitionFromName = DalCommon.GetStoreName(item.RequisitionFrom); item.RequisitionToName = DalCommon.GetStoreName(item.RequisitionTo); } |
现在,如果您实际上需要为所有数据分配这些属性,并且数据可以是任意大的,那么您需要制定一个策略,如何做到这一点。非常简单的选择是将它们保存到数据库中的一个新表中,然后处理的数据的大小将只受数据库容量的限制。
如果在
尽管
简而言之:
- 不带
AsEnumerable() =在SQL中进行过滤和排序 - 使用
AsEnumerable() ,然后将where 或orderby 应用于带到内存中的整个集合。
只能在内存中的集合上运行用户定义的函数(因为LINQ to SQL将无法将函数解释为SQL代码)。所以您的第二个代码片段(没有
唯一的另一种选择是在SQL本身中应用用户定义的函数。
好了,伙计们,我注意到你们所有人的不同观点,想出了这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var Data = (from r in _context.PRD_ChemProdReq.AsEnumerable() //where r.RecordStatus =="NCF" join rf in _context.SYS_Store on (r.RequisitionFrom==null?0: r.RequisitionFrom) equals rf.StoreID into requisitionfrom from rf in requisitionfrom.DefaultIfEmpty() join rt in _context.SYS_Store on (r.RequisitionTo == null ? 0 : r.RequisitionTo) equals rt.StoreID into requisitionto from rt in requisitionto.DefaultIfEmpty() orderby r.RequisitionNo descending select new PRDChemProdReq { RequisitionID = r.RequisitionID, RequisitionNo = r.RequisitionNo, RequisitionCategory = DalCommon.ReturnRequisitionCategory(r.RequisitionCategory), RequisitionType = r.RequisitionType =="UR" ?"Urgent" :"Normal", ReqRaisedOn = (Convert.ToDateTime(r.ReqRaisedOn)).ToString("dd'/'MM'/'yyyy"), RecordStatus = (r.RecordStatus=="NCF"?"Not Confirmed":"Approved"), RequisitionFromName = (rf==null? null: rf.StoreName), RequisitionToName = (rt == null ? null : rt.StoreName) }); |
首先,我删除了tolist(),它只执行调用aseNumerable()时已经完成的查询。没有点可以执行同一查询两次。另外,我在select块中的自定义方法调用也起到了减缓速度的主要作用。我尝试减少方法调用,而在可能的情况下使用join。它使事情变得相当快。谢谢大家。