On Wed, May 31, 2017 at 12:09 AM, Alexander Zaytsev <haz...@gmail.com> wrote:
> Hi,
>
> I want to start talking about the JSON support for NHibernate. It seems this
> is a long-awaited feature, which, if properly implemented can give us some
> advantages over the other "shall not be named here" ORM.
>
> I'll try to summarize the current state and what's needed to be done to
> implement this feature.
>
> Current support of RDBMs engines
>
> The current state of the RDBMS (not all of them, only the ones we care most
> about)
>
> Postgres 9.3+ - Supports json and jsonb column types.
> Microsoft SQL Server 2016 - Supports some JSON functions over an NVARCHAR
> columns

One other important thought: remember that 2016 is Windows 10+ only.
Probably your SQL Server is being hosted on a current Windows Server
version. Probably. But for some developers, myself anyway, I am still
running on Windows 7. No plans to upgrade in the near future unless
something changes economically speaking.

> Oracle 12c - Supports some JSON functions over VARCHAR2, CLOB, and BLOB
> columns
> SQLite - Has a loadable JSON extension
> MySQL 5.7+ - Supports some JSON functions over JSON column type
> Firebird - no support.
>
>
> Persisting/Loading
>
> The challenge here is that different RDBMS use different approaches how they
> store the JSON data. Also, as Microsoft has decided to store JSON as a
> string it's most likely that there will be no DbType.Json added to the
> ADO.NET.
>
> There are several sensible ways to represent json data on the client side:
>
> as a String
> as a POCO object
> as a JObject (JSON.NET) or JsonObject (System.Json)
>
>
> Querying RDBMS
>
> It seems that there are 2 main approaches how the RDBMS support querying the
> JSON data:
>
> Arrow (Postgres, MySQL) or dot notations (Oracle)
> A single function to extract part of the json data: json_extract (MySQL,
> SQLite) or json_extract_path (Postgres)
> Two functions to extract part of the json data: json_value (to return a
> scalar value) and json_query (to return object or array). This is supported
> by SQL Server & Oracle
> SQL Server will return NULL or throw an error (depending on a server
> configuration) if the incorrect function is used.
>
> For [2] and [3] functions the first operand is a JSON expression and the
> second argument is a JSON path expression as defined here
> http://goessner.net/articles/JsonPath/.
>
> It seems as the first phase it would be sensible to provide JSON querying
> support only for HQL and Linq. Criteria & QueryOver can be implemented as a
> second phase (if at all).
>
> Dialects: because of [3] we will need to register 2 JSON querying functions
> which will be mapped to a single function for Postgres, MySQL and SQLite.
>
> HQL: We will not support the arrow or dot notations as it will require
> intensive AST tree rewrites.
>
> LINQ:
>
> Because of the peculiarity of SQL Server (json_query vs json_value), we will
> need to predict the intention of the user what they want to query: a part of
> a JSON or a scalar value. It seems to be easy in case of POCO classes, but
> can be tricky with String/JToken. To parse the Linq-2-JSON expression we
> will need to identify a root object of the query, and then build a JSON
> expression from this root object. Most likely we will need to do some
> analysis before the Re-Linq to prevent expansion of a QueryModel in case of
> JSON expression.
>
> Some LINQ examples:
>
> Given the Entity with a Data property storing following JSON object (from
> http://jsonpath.com/):
>
> {
>   "firstName": "John",
>   "lastName" : "doe",
>   "age"      : 26,
>   "address"  : {
>     "streetAddress": "naist street",
>     "city"         : "Nara",
>     "postalCode"   : "630-0192"
>   },
>   "phoneNumbers": [
>     {
>       "type"  : "iPhone",
>       "number": "0123-4567-8888"
>     },
>     {
>       "type"  : "home",
>       "number": "0123-4567-8910"
>     }
>   ]
> }
>
> using (var session = OpenSession())
> using (session.BeginTransaction())
> {
> var entities = (
> from e in session.Query<Entity>()
> where (string) JObject.Parse(e.Data)["firstName"] == "John" // This
> translates to WHERE JSON_VALUE(e.Data, "$.firstName") = "John"
> select e).ToList();
> }
>
> using (var session = OpenSession())
> using (session.BeginTransaction())
> {
> var entities = (
> from e in session.Query<Entity>()
> where (string) JObject.Parse(e.Data)["address"]["city"] == "Nara" // This
> translates to WHERE JSON_VALUE(e.Data, "$.address.city") = "Nara"
> select e).ToList();
> }
>
> using (var session = OpenSession())
> using (session.BeginTransaction())
> {
> var entities = (
> from e in session.Query<Entity>()
> select JObject.Parse(e.Data)["phoneNumbers"].Select(x =>
> x["type"])).ToList(); // This translates to SELECT JSON_QUERY(e.Data,
> "$.phoneNumbers[*].type")
> }
>
> All suggestions and comments are welcome.
>
> Best Regards,
> Alexander
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "nhibernate-development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to nhibernate-development+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to nhibernate-development+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to