标签:客户 逻辑 mod hat tin 技术 代码 rar 标记
使用asp.net core开发时避免不了要用一个合适的分页组件来让前端获取分页数据。github上面有一个开源的分页组件在这方面很适合我的使用,于是我把他的文档翻译一下,随后会分析它里面的源码。这是第一篇,介绍它如何使用。
Sieves是一个.net core下面的简单、干净并且可扩展的框架,它对外暴露了排序,过滤和分页的功能。
在本例中,考虑一个带有Post实体的应用程序。在获取所有可用的帖子时,我们将使用Sieve添加排序、过滤和分页功能。
在StartUp.cs文件中编辑ConfigureService方法,将SieveProcessor服务注入进去:
services.AddScoped<SieveProcessor>();
Sieve只会对标记有Sieve Attribute的属性(例如:[Sieve(Cansort=true,CanFilter=true)])进行排序或者过滤,所以,在我们的Post的例子中:
public int Id { get; set; } [Sieve(CanFilter = true, CanSort = true)] public string Title { get; set; } [Sieve(CanFilter = true, CanSort = true)] public int LikeCount { get; set; } [Sieve(CanFilter = true, CanSort = true)] public int CommentCount { get; set; } [Sieve(CanFilter = true, CanSort = true, Name = "created")] public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
Name参数可以为客户端提供一个不一样的名字
NOTE:你可以使用Fluent API实现一样的功能,就像EF Core中的Fluent Api(IEntityTypeConfiguration)一样的道理和用法。
在下面这个Action中处理返回的Post,使用SieveModel来获取排序过滤以及分页查询参数。同时,将SieveProcessor注入到你的Controller中,只要使用它的Apply<TEntity>方法就可以了:
[HttpGet] public JsonResult GetPosts(SieveModel sieveModel) { var result = _dbContext.Posts.AsNoTracking(); // Makes read-only queries faster result = _sieveProcessor.Apply(sieveModel, result); // Returns `result` after applying the sort/filter/page query in `SieveModel` to it return Json(result.ToList()); }
你也可以通过应用这个方法中的可选参数来显式的指定你的意图,比如你只想要过滤或者配许,或者分页。具体查看它的Api吧。
GET /GetPosts
?sorts= LikeCount,CommentCount,-created // sort by likes, then comments, then descendingly by date created
&filters= LikeCount>10, Title@=awesome title, // filter to posts with more than 10 likes, and a title that contains the phrase "awesome title"
&page= 1 // get the first page...
&pageSize= 10 // ...which contains 10 posts
如果你想要添加自定义的排序和过滤方法,注入ISieveCustomSortMethods
或ISieveCustomFilterMethods
这两个接口的实现就可以了,Sieve会查询到你注入的这两个接口并应用他们。
举例来说:
services.AddScoped<ISieveCustomSortMethods, SieveCustomSortMethods>();
services.AddScoped<ISieveCustomFilterMethods, SieveCustomFilterMethods>();
SieveCustomSortMethodsOfPosts
是下面这样的:
public class SieveCustomSortMethods : ISieveCustomSortMethods { public IQueryable<Post> Popularity(IQueryable<Post> source, bool useThenBy, bool desc) // The method is given an indicator of weather to use ThenBy(), and if the query is descending { var result = useThenBy ? ((IOrderedQueryable<Post>)source).ThenBy(p => p.LikeCount) : // ThenBy only works on IOrderedQueryable<TEntity> source.OrderBy(p => p.LikeCount) .ThenBy(p => p.CommentCount) .ThenBy(p => p.DateCreated); return result; // Must return modified IQueryable<TEntity> } }
SieveCustomFilterMethods
:
public class SieveCustomFilterMethods : ISieveCustomFilterMethods { public IQueryable<Post> IsNew(IQueryable<Post> source, string op, string[] values) // The method is given the {Operator} & {Value} { var result = source.Where(p => p.LikeCount < 100 && p.CommentCount < 5); return result; // Must return modified IQueryable<TEntity> } }
使用ASP.NET Core options pattern这种方式来配置SieveOption,告诉Sieve从哪里找到配置。比如:
services.Configure<SieveOptions>(Configuration.GetSection("Sieve"));
你可以在Json文件中添加配置:
{ "Sieve": { "CaseSensitive": "boolean: should property names be case-sensitive? Defaults to false", "DefaultPageSize": "int number: optional number to fallback to when no page argument is given. Set <=0 to disable paging if no pageSize is specified (default).", "MaxPageSize": "int number: maximum allowed page size. Set <=0 to make infinite (default)", "ThrowExceptions": "boolean: should Sieve throw exceptions instead of silently failing? Defaults to false" } }
上面那些步骤你都做了的话,你可以发送一个GET请求,请求中携带排序、过滤和分页查询参数,下面一个例子:
GET /GetPosts
?sorts= LikeCount,CommentCount,-created // sort by likes, then comments, then descendingly by date created
&filters= LikeCount>10, Title@=awesome title, // filter to posts with more than 10 likes, and a title that contains the phrase "awesome title"
&page= 1 // get the first page...
&pageSize= 10 // ...which contains 10 posts
更多的信息:
sorts是按逗号分隔的有序属性名
列表。在名称之前添加一个“-”将切换到递减排序。
(LikeCount|CommentCount)
>10询问LikeCount或CommentCount是否为>10。②操作符是下面要介绍的操作符中的一种(下面会介绍)。③值是会被过滤功能所采用的值。你同样可以使用多个值(作为OR逻辑),比如Title@=new|hot
会返回Title包含“new”或者“hot"的Post。注意:
//代码直接摘抄自这个项目的github上面的issure中,你可以自己打开看
From my own experience I‘d like the ability to get the total count while filtering and paginating. When paginating result.Count() will be the number of records on that page, not the total number of records. This alone doesn‘t give enough information to, say, power a pagination component as we don‘t know the number of total pages/records. Though, if I‘m wrong I‘d be pretty happy as I‘m currently doing this as a workaround: public async Task<IActionResult> GetQuestions(SieveModel sieveModel) { var questions = _context.Questions.AsNoTracking(); questions = _sieveProcessor.Apply(sieveModel, questions); var total = _context.Questions.AsNoTracking(); total = _sieveProcessor.Apply(sieveModel, total, applySorting: false, applyPagination: false); Request.HttpContext.Response.Headers.Add("X-Total-Count", total.Count().ToString()); return Ok(questions); }
You‘ll have to write a custom filter for that. Here‘s an example for v>=1.3.7: public class SieveCustomFilterMethods : ISieveCustomFilterMethods { public IQueryable<Post> AuthorIsAnyOf(IQueryable<Post> source, string op, string value) { var result = source.Where(p => value.Split(‘|‘).Contains(p.Author)); return result; } } Then inject the class: services.AddScoped<ISieveCustomFilterMethods, SieveCustomFilterMethods>();. Now you can send requests in the form: & AuthorIsAnyOf == Bad Pitt|Mel Gibson Note I‘m using the pipe character (|) instead of a comma because Sieve uses commas to separate filter terms.
You can do that with a custom filters so for example: The equivalent of your (title, body, author)@=ABC would be PostSearch@=ABC with: public class SieveCustomFilterMethods : ISieveCustomFilterMethods { public IQueryable<Post> PostSearch(IQueryable<Post> source, string op, string value) { if (op == "@=") { var result = source.Where(p => p.Title.Contains(value) || p.Body.Contains(value) || p.Author.Contains(value)); return result; } else { return source; } } } This would save you having to send requests with the same property names repeated every time, as well as allow for any additional logic you might need. That being said, I understand the need for OR logic, especially when you need to query unknown arbitrary parameters each time. I was working on an version where a | would donate OR (similar to , currently denoting AND). I think this would allow for more complex logic than your suggested implementation - at the cost of being less concise and more redundant (ie. instead of (p1,p1)@=ABC, you‘d have p1@=ABC|p2@=ABC. Let me know what you think - would that work for your use case or am I missing something? Really glad you like Sieve :D.
asp.net core 排序过滤分页组件:sieve(1)
标签:客户 逻辑 mod hat tin 技术 代码 rar 标记
原文地址:https://www.cnblogs.com/pangjianxin/p/10785615.html