Skip to content

Commit 688daa1

Browse files
committed
Update readme and bump version
1 parent 0ac85fa commit 688daa1

File tree

2 files changed

+110
-3
lines changed

2 files changed

+110
-3
lines changed

README.md

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ The parser aims to be Database and Provider agnostic. It currently targets Netst
1515
* Sql Server
1616
* PostgreSQL
1717

18+
If you intend to filter your dataset, the default configuration assumes your IQueryable uses a provider with support for .ToString() on DateTime and numeric types. Please note that EFCore will not fail but instead fall back to client evaluation if this requirement is not met. I have mixed feelings about this. I believe client evaluation should be opt-in and not opt-out.
19+
1820
jQuery Datatables
1921
========================
2022

@@ -114,7 +116,112 @@ The following snippets were taken from the aspnet-core-sample project also locat
114116

115117
The included Dockerfile-websample builds, packages and runs the web sample project in a docker image. No tools, frameworks or runtimes are required on the host machine. The image has been published to docker for your convenience.
116118

117-
docker run -p 80:80 garvincasimir/datatables-aspnet-core-sample:0.0.2
119+
docker run -p 80:80 garvincasimir/datatables-aspnet-core-sample:0.0.2
120+
121+
Custom Filter Expressions
122+
========================
123+
The parser builds a set of expressions based on the settings and filter text sent from Datatables. The end result is a *WHERE* clause which looks something like this:
124+
125+
```
126+
FROM [People] AS [val]
127+
WHERE ((((CASE
128+
WHEN CHARINDEX(N'cromie', LOWER([val].[FirstName])) > 0
129+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
130+
END | CASE
131+
WHEN CHARINDEX(N'cromie', LOWER([val].[LastName])) > 0
132+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
133+
END) | CASE
134+
WHEN CHARINDEX(N'cromie', LOWER(CONVERT(VARCHAR(100), [val].[BirthDate]))) > 0
135+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
136+
END) | CASE
137+
WHEN CHARINDEX(N'cromie', LOWER(CONVERT(VARCHAR(100), [val].[Weight]))) > 0
138+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
139+
END) | CASE
140+
WHEN CHARINDEX(N'cromie', LOWER(CONVERT(VARCHAR(11), [val].[Children]))) > 0
141+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
142+
END) = 1
143+
```
144+
145+
In the above example, each of the case statements will attempt to find the filter text 'cromie' within a string representation of the properties from *T*. The exact mechanics and syntax will vary by provider and db engine but this is an example of the actual query sent to your backend database.
146+
147+
The expression generated by the parser looks like this:
148+
149+
```
150+
where val.FirstName.ToLower().Contains("cromie") || val.LastName.ToLower().Contains("cromie") || val.BirthDate.ToString().ToLower().Contains("cromie") || val.Weight.ToString().ToLower().Contains("cromie") || val.Children.ToString().ToLower().Contains("cromie")
151+
```
152+
153+
What is missing in the above expression is the ability to format dates to match the client side. So it may seem strange to a user if they enter a date in the filter text box and no results are returned. It would be nice if providers just supported *DateTime.ToString(string format)* right? Even if they did, the format strings expected by db engines are not consistent at all. As a result, I decided to expose some of the internals of the parser and allow library users to substitute .ToString() with a custom expression.
154+
155+
For example, if your provider does support *DateTime.ToString(string format)*, you can substitute .ToString() with that expression after initializing the parser. This must be explicitly called for each applicable property.
156+
157+
```
158+
var parser = new Parser<Person>(p, context.People)
159+
.SetConverter(x => x.BirthDate, x => x.BirthDate.ToString("M/dd/yyyy"))
160+
.SetConverter(x => x.LastUpdated, x => x.LastUpdated.ToString("M/dd/yyyy"));
161+
```
162+
163+
**EF Core 2**
164+
165+
In EF Core 2 you can map user defined and system scalar valued functions and use them for formatting. The following is an example for SQL Server >= 2012.
166+
167+
PersonContext.cs
168+
```
169+
using Microsoft.EntityFrameworkCore;
170+
using System;
171+
172+
namespace DataTablesParser.Tests
173+
{
174+
public class PersonContext : DbContext
175+
{
176+
public PersonContext(){ }
177+
178+
public PersonContext(DbContextOptions<PersonContext> options)
179+
: base(options){ }
180+
181+
//Sql Server >= 2012
182+
//https://docs.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql
183+
[DbFunction]
184+
public static string Format(DateTime data,string format)
185+
{
186+
throw new Exception();
187+
}
188+
189+
public DbSet<Person> People { get; set; }
190+
}
191+
}
192+
193+
```
194+
Parser initialization
195+
196+
```
197+
198+
var parser = new Parser<Person>(p, context.People)
199+
.SetConverter(x => x.BirthDate, x => PersonContext.Format(x.BirthDate,"M/dd/yyyy"));
200+
```
201+
202+
The *WHERE* clause now looks like this:
203+
204+
```
205+
WHERE ((((CASE
206+
WHEN CHARINDEX(N'9/03/1953', LOWER([val].[FirstName])) > 0
207+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
208+
END | CASE
209+
WHEN CHARINDEX(N'9/03/1953', LOWER([val].[LastName])) > 0
210+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
211+
END) | CASE
212+
WHEN CHARINDEX(N'9/03/1953', LOWER(Format([val].[BirthDate], N'M/dd/yyyy'))) > 0
213+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
214+
END) | CASE
215+
WHEN CHARINDEX(N'9/03/1953', LOWER(CONVERT(VARCHAR(100), [val].[Weight]))) > 0
216+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
217+
END) | CASE
218+
WHEN CHARINDEX(N'9/03/1953', LOWER(CONVERT(VARCHAR(11), [val].[Children]))) > 0
219+
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
220+
END) = 1
221+
```
222+
223+
For examples using MySQL and PostgreSQL please see the test project
224+
118225

119226
Installation
120227
========================
@@ -148,7 +255,7 @@ I welcome any suggestions for improvement, contributions, questions or issues wi
148255
* The diff for your pull request should only show changes related to your fix/addition (Some editors create unnecessary changes).
149256
* When possible include tests that cover the features/changes in your pull request
150257
* Before you submit make sure the existing tests pass with your changes
151-
* Also, issues that are accompanied by failing tests will probably get handleded quicker
258+
* Also, issues that are accompanied by failing tests will probably get handled quicker
152259

153260
Contact
154261
========================

src/DatatablesParser/DatatablesParser.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>netstandard1.3</TargetFramework>
55
<AssemblyName>DatatablesParser</AssemblyName>
66
<PackageId>DatatablesParser-core</PackageId>
7-
<PackageVersion>1.0.0</PackageVersion>
7+
<PackageVersion>1.1.0</PackageVersion>
88
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
99
<PackageTags>C# Datatables Datatables.net javascript parser json Linq entity framework asp.net mvc grid table database query builder core</PackageTags>
1010
<PackageProjectUrl>https://github.com/garvincasimir/csharp-datatables-parser</PackageProjectUrl>

0 commit comments

Comments
 (0)