Imported function in Entity Framework Where clause? - entity-framework

Is it possible to use a function import in a where clause in entity framework? I have tried the following, but I get a rather cryptic exception to which I cannot find any information about:
var q = MyContext.MyEntities.Where("MyContext.MyFunction(it.ID)")
(The function is set to return a Boolean)
System.Data.EntitySqlException: 'MyContext.MyFunction' cannot be resolved into a valid type constructor or function., near WHERE predicate, line 6, column 21..
Regards
Lee

The query you are trying to write is composing a call to a FunctionImport with a query over an EntitySet.
But because FunctionImports are wrappers around StoredProcedures, which are non-composable, this just won't work.
In order for something like this to work, theoretically the function would need to be a wrapper around something composable like a TVF (Table Value Function). But unfortunately TVFs aren't supported in the Entity Framework today.
Alex

I don't think you want to pass this expression as a string. You want a proper lambda expression like:
MyContext.MyEntities.Where( entity => MyContext.MyFunction(entity.ID ) );

Related

How to use PostgreSQL xmlexists() function in Hibernate HQL query?

I want to create HQL query with xmlexists() function but I get an error.
My code:
Query query = session.createQuery("From XMLTable AS tb WHERE xmlexists('//food[#id = \"1\"]' PASSING BY REF tb.xmlData)");
List list = query.list();
list.forEach(obj -> {
printSth((XMLTable) obj);
});
ERROR:
ERROR: line 1:77: unexpected token: PASSING
I also tried in pgAdmin 4 and there everything works fine. I guess that this is a syntax problem in HQL.
The problem seems to be related to the unorthodox syntax of the function you use.
An obvious solution for the problem would be to use session.createNativeQuery() instead of a JPQL query. You can then (and should) use plain SQL as the method argument.
Another solution might be to extend the dialect class Hibernate provides for PostgreSQL and register a new function implementation for xmlexists(). I am not sure if that would work though.

Replacement for deprecated PostgresDataType.JSON?

I'm using JOOQ with PostgreSQL, and trying to implement a query like this:
INSERT INTO dest_table (id,name,custom_data)
SELECT key as id,
nameproperty as name,
CONCAT('{"propertyA": "',property_a,'", "propertyB": "',property_b,'","propertyC": "',property_c,'"}')::json as custom_data
FROM source_table
The concatenation/JSON bit is what I'm here to ask about. I actually have managed to get it working, but only by using this (Kotlin):
val concatBits = mutableListOf<Field<Any>>()
... build up various bits of the concatenation ...
val concatField = concat(*(concatBits.toTypedArray())).cast(PostgresDataType.JSON)
It concerns me that PostgresDataType is deprecated. The documentation says I should use SQLDataType instead, but it has no JSON value.
What's the recommended way to do this?
EDIT: a bit more information ...
I'm building the query like this:
val innerSelectFields = listOf(
field("key").`as`(DEST_TABLE.ID),
field("nameproperty").`as`(DEST_TABLE.NAME),
concatField.`as`(DEST_TABLE.CUSTOM_DATA)
)
val innerSelect = dslContext
.select(innerSelectFields)
.from(table("source_table"))
val insertInto = dslContext
.insertInto(DEST_TABLE)
.select(innerSelect)
The initial query I posted is slightly misleading, as the resulting SQL from this code doesn't have the
(id,name,custom_data) part.
Also, in case it matters, "source_table" is a temporary table, created during runtime, so there are no autogenerated classes for it.
jOOQ currently doesn't support the JSON data type out of the box. The main reason is that it is unclear what Java type to bind a JSON data structure to, as the JDK doesn't have such a standard type, and jOOQ will not prefer one third party library over the other.
The currently recommended approach is to create your own custom data type binding for your preferred third party JSON library:
https://www.jooq.org/doc/latest/manual/code-generation/custom-data-type-bindings
In that case, you will no longer need to explicitly cast your bind variable to some JSON type, because your binding will take care of that transparently.

Dynamic LINQ and Kendo MVC wrappers

I'm using System.Linq.Dynamic.Core and EntityFramework library to generate a query like this:
var q = context.Items.Select("new(SomeProperty)")
The q is of type IQueryable at the moment. I can successfully apply OrderBy, Take, Skip and then execute the query.
But if I try to use the extension method from Kendo, things go south:
var results = q.ToDataSourceResult(new DataSourceRequest())
I get an Exception:
NotSupportedException
Unknown LINQ expression of type 'Dynamic'.
I know that the ToDataSourceResult method adds the OrderBy, Take and Skip to the IQueryable to do the paging so that's the most likely source of the problem (it does create a dynamic expression if the object is object or IDynamicMetaObjectProvider)
Any idea how to workaround this?
You could also try this package https://github.com/StefH/KendoGridBinderEx which is created for Kendo Grid queries and uses System.Linq.Dynamic.Core

Using case classes in lifted Slick

In ScalaQuery it seemed to be possible to use case classes in table definitions. e.g. https://github.com/szeiger/scala-query/blob/master/src/test/scala/scala/slick/test/ql/MapperTest.scala#L26
But this syntax doesn't work in Slick. Specifically, the method <> is not available.
Is there a way to use case classes in lifted Slick without boilerplate mapping?
It still works. See https://github.com/slick/slick/blob/1.0.1/slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/MapperTest.scala . Be aware that you currently cannot map a single column, see https://github.com/slick/slick/issues/40 .
The error message you got could come from the component types of your projection not matching the component types of your case class. The <> method is added using an implicit conversion that is only applied if the types match.

Why the 'it' in Entity Framework and EntityDataSource examples?

Dumb question I'm sure, but why does Entity Framework EntityDataSource object require the where clause to contain 'it' as the first part of the object selector?
The documentation for the where clause (http://msdn.microsoft.com/en-us/library/cc488531.aspx) states that the string is passed directly to the ObjectQuery(T), so I should be able to pass in (for example) "x.OnlineOrderFlag = TRUE" where x is anything that makes sense in a predicate, however the clause only works if I pass in "it.OnlineOrderFlag = TRUE"
All of the Microsoft examples use 'it' so what am I missing?
Steve Davies
It looks like "it" is just an implicit parameter name. In query expressions this is provided by the range variable, but you don't specify the parameter name in the call to Where, so it looks like it just uses "it" implicitly.
I agree that it's poorly documented though :(