当前位置: 首页 > 编程语言 > C#

FreezelinqIQueryable(AsToList().AsQueryable()会做)分享

时间:2023-04-10 19:50:37 C#

FreezelinqIQueryable(AsToList().AsQueryable()会做)有没有办法冻结IQueryable,这样当命中数据库不会向查询添加另一个连接?例如,我可以使用.ToList()来冻结查询,但这会对性能产生影响,因为我所做的任何过滤都在中间层进行,并且我不会从数据库服务器上的预过滤中获得任何性能提升?为清楚起见进行编辑:我有一个OData服务,它返回一个IQueryable,客户端可以根据需要过滤/排序/项目。我只是想阻止他们提取更多数据。我可以通过执行ToList().AsQueryable()来做到这一点,但它失去了lazyLoading的优势,并且失去了允许客户端过滤请求的全部目的。我看到的一个选项是设置:EnableQueryAttribute.AllowedQueryOptions以排除Expand,但即使我的初始Query已展开,客户端仍然无法选择那些部分。我假设您实际上有一个IQueryable而不是IQueryable。如果您不希望您的客户端访问所有IQueryable方法,请不要返回IQueryable。因为你希望它们只被过滤/排序/投影,创建一个包含IQueryable的对象,但只公开你需要的方法,并使用它:publicinterfaceIDataResult{IDataResultFilterBy(Expression>predicate);IDataResultProjectTo(表达式>谓词);IDataResultSortBy(表达式>keySelector);IDataResultSortByDescending(表达式>keySelector);列表ToList();IEnumerableAsEnumerable();}publicclassDataResult:IDataResult{privateIQueryableQuery{get;放;}publicDataResult(IQueryable)originalQuery{this.Query=originalQuery;}publicIDataResultFilterBy(Expression>predicate){returnnewDataResult(this.Query.Where(predicate));}publicIDataResultSortBy(Expression>keySelector){returnnewDataResult(this.Query.OrderBy(keySelector));}publicIDataResultSortByDescending(Expression>keySelector){returnnewDataResult(this.Query.OrderByDescending(keySelector));}publicIDataResultProjectTo(Expression>predicate){returnnewDataResult(this.Query.Select(predicate));}公共列表ToList(){返回this.Query.ToList();}publicIEnumerableAsEnumerable(){returnthis.Query.AsEnumerable();通过这种方式,您还可以防止应用程序相关的EF和DB相关的依赖项对IQueryable方法的任何更改都将包含在此类中,而不是到处都是。所以我(认为)尝试了同样的方法,我发现的唯一解决方案是在SQLServer管理器中使用TVF。我假设EF6.1.1和WebAPI。以下是一些步骤:(1)创建过程(如果需要可以添加参数):CREATEPROCEDURE[dbo].[GetArticleApiKey]@anvarchar(max)ASSELECTa.*FROM[dbo].[Blogs]b,[dbo].[文章]aWHEREb.ApiKey=@aANDb.Id=a.Blog_Id如果您需要在代码优先中使用它,您可以在DbContext构造函数中使用Database.SetInitializerInitializer。(2)下载这个nuget包。它启用可查询的存储过程。这是该项目的基础。(3)将以下内容添加到您的DbContext:}(4)将存储过程添加到您的上下文中:publicObjectResultGetArticleApiKey(stringapiKey){varapikeyParameter=newObjectParameter(ApiKeyParameter,apiKey);//确保验证这一点,因为sql注入((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("GetArticleApiKey",apikeyParameter);(5)您现在可以在您的控制器中使用此函数并对其进行预过滤。之后所有Odata查询仍然是可能的,但仅限于sql-procedure的结果。context.GetArticleApiKey("MyApiKey").AsQueryable();希望我能找到你要找的东西。在我看来,最简单的方法是将IQueryable转换为Func>。这样你就不会失去懒惰的一面,但你肯定会失去在数据库上建立进一步连接的能力。这有多简单:}publicstaticFunc>Freeze(thisIQueryablequeryable,Expression>predicate,Expression>projection){return()=>queryable.Where(predicate).Select(projection).ToList();然后你可以这样做:IQueryablequery=...;Func>frozen=query.Freeze(t=>t>10,t=>t);列表结果=frozen.Invoke();下面是一些基本代码,以便对其进行测试:publicIEnumerableTest(){Console.WriteLine(1);收益回报1;控制台.WriteLine(2);收益回报2;现在我称它为:IQueryablequery=Test().AsQueryable();Console.WriteLine("冻结前");Func>frozen=query.Freeze(t=>t>10,t=>t);Console.WriteLine("冻结后");Console.WriteLine("调用前");列出结果1=frozen.Invoke();列出结果2=frozen.Invoke();Console.WriteLine("调用后");在控制台上,我得到这个:在调用1212之后冻结之前冻结之前调用1212如你所见,它是惰性的,只在调用时运行详细了解C#学习教程,希望大家多多关注——本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: