NHibernate error system.object[] when retrieving multiple entities in one query - select

I have a HQL query like this:
string QueryString = select client, transporter
from BaseClient as client, BaseTrans as transporter
where client.tr = transporter.Id and transporter.badge = 1
order by transporter.date;
But when I use this hql I receive the following error :
The value "System.Object[]" is not of type "xxx" and cannot be used in this generic collection.
Parameter name: value
Just like Example but, when I omit the Transporter entity in my select it works.
Like :
string QueryString = select client
from BaseClient as client, BaseTrans as transporter
where client.tr = transporter.Id and transporter.badge = 1
order by transporter.date;
But I need transporter in my select, because I use order by.
By the way, I have 2 hbm Client.hbm.xml and Transporter.hbm.xml. Each hbm have their own Class and Table.
i call it with :
IQuery requete = this.CreateQuery(QueryString);
IList<Client> executions = requete.List<Client>();
it hang on this line, when hibernate try to convert to the list

This happens because your result-set will likely be a multi-dimensional array where the first column represents a Client and the 2nd column contains a Transporter.
What happens if you change your code like this:
IQuery requete = this.CreateQuery(QueryString);
var result = requete.List();
var clients = result[0] as IEnumerable<Client>;
(I have no NHibernate installed on this system so I cannot just test something out quickly without creating and setting up a new project. :)

Related

EF Core completely ignores my selected properties in select

As I understand it, the following code should generate a query containing only the RouteId, RouteNo, and ShipId
var tow = (from t in _context.AllTowData
where t.RouteId == id
orderby t.RouteNo descending
select new TowDefaults {
Id = t.RouteId,
TowNo = t.RouteNo,
ShipId = t.ShipId,
LastTow = t.RouteNo
})
.FirstOrDefault();
However, I get:
SELECT v.route_id, v.route_no, v.tow_id, v.analysis_complete, v.checks_complete, v.cpr_id, v.date_created, v.date_last_modified, v.factor, v.fromportname, v.instrument_data_file, v.instrument_id, v.internal_number, v.mastername, v.message, v.miles_per_division, v.month, v.number_of_samples, v.number_of_samples_analysed_fully, v.prop_setting, v.route_status, v.sampled_mileage, v.serial_no_per_calendar_month, v.ship_speed, v.silk_reading_end, v.silk_reading_start, v.toportname, v.tow_mileage, v.validity, v.year
FROM view_all_tow_data AS v
WHERE v.route_id = '#__id_0'
ORDER BY v.route_no DESC
LIMIT 1
That's every column except the explicitly requested ShipId! What am I doing wrong?
This happens using both a SQL Server and a PostGres database
The property ShipIdis not mapped, either by a [NotMapped] annotation or a mapping instruction. As far as EF is concerned, the property doesn't exist. This has two effects:
EF "notices" that there's an unknown part the final Select and it switches to client-side evaluation (because it's a final Select). Which means: it translates the query before the Select into SQL which doesn't contain the ShipId column, executes it, and materializes full AllTowData entities.
It evaluates the Select client-side and returns the requested TowDefaults objects in which ShipId has its default value, or any value you initialize in C# code, but nothing from the database.
You can verify this by checking _context.AllTowData.Local after the query: it will contain all AllTowData entities that pass the filter.
From your question it's impossible to tell what you should do. Maybe you can map the property to a column in the view. If not, you should remove it from the LINQ query. Using it in LINQ anywhere but in a final Select will cause a runtime exception.

How to use a list as a parameter source for SQL queries with Vertx JDBC Client?

I have a Vert.x web application that needs to query an AWS RDS instance running Postgres 10.7. The Vert.x JDBC client is io.vertx:vertx-jdbc-client:3.8.4. I want to query a table with the constraint that a certain column's value is included in a set of values:
select from table where column in/any (?)
I followed the Vertx documentation, which says to create a JsonArray and populate it with the values to inject into the query. The column is of type text and the list that I want to match on is a Java ArrayList<String>. My query code looks like:
String sql = "SELECT a FROM table WHERE col IN (?)";
List<String> values = someObject.someField();
sqlClient.getConnection(connectionResult -> {
if (connectionResult.failed()) {
// handle
} else {
SQLConnection connection = connectionResult.result();
JsonArray params = new JsonArray()
.add(values);
connection.queryWithParams(sql, params, queryResult -> {
if (queryResult.failed()) {
// handle
} else {
// parse
}
});
}
});
The query fails with the error: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of io.vertx.core.json.JsonArray. Use setObject() with an explicit Types value to specify the type to use.
I know that in the worst case, I can create a literal SQL string where col in (?, ?, ?, ..., ?) and add each String from the list to a JsonArray, but there must be a way to just add the ArrayList<String> as a parameter and keep the query simple. How can I specify a list of values to match against in my query?
The Vert.x JDBC Client does not support array parameters in queries.
However it is possible with the Vert.x Pg Client, which does not depend on JDBC. You need to modify your query first:
SELECT a FROM table WHERE col = ANY(?)
Then:
pgClient.preparedQuery(query, Tuple.of(possibleValues), collector, handler);

Not able to use IN query in LINQ with Entity Framework

I am using EF Framework to retrieve the data from SQL DB.
Sub Request Table looks like below:
In this table "org_assigneddept" is foreign key to another Department Table.
I have list of Departments as Input and I want to retrieve only those rows from DB whose org_assigneddept is matching the list.
Please find my whole code:-
private List<EventRequestDetailsViewModel> GetSummaryAssignedDeptEventRequests(List<EmpRoleDeptViewModel> vmDept)
{
List<EventRequestDetailsViewModel> vmEventRequestDeptSummary = new List<EventRequestDetailsViewModel>();
RequestBLL getRequestBLL = new RequestBLL();
Guid subRequestStatusId = getRequestBLL.GetRequestStatusId("Open");
using (var ctxGetEventRequestSumm = new STREAM_EMPLOYEEDBEntities())
{
vmEventRequestDeptSummary = (from ers in ctxGetEventRequestSumm.SubRequests
where vmDept.Any(dep=>dep.DeptId == ers.org_assigneddept)
select new EventRequestDetailsViewModel
{
SubRequestId = ers.org_subreqid
}).ToList();
}
}
It is giving the following error at the LINQ Query level:-
System.NotSupportedException: 'Unable to create a constant value of
type 'Application.Business.DLL.EmpRoleDeptViewModel'. Only primitive
types or enumeration types are supported in this context.'
Please let me know as how can I achieve the result
You cannot pass the department VMs to SQL, it doesn't know what those are.
// Extract the IDs from the view models.. Now a list of primitive types..
var departmentIds = vmDept.Select(x => x.DeptId).ToList();
then in your select statement...
..
where departmentIds.Contains(id=> id == ers.org_assigneddept)
..

OrientDB select record count from all graph classes

Any way to get record count for each graph class (V, E and their subclasses)?
I tried to build query in SQL format for current case:
SELECT #class, count(*) FROM V GROUP BY #class
SELECT #class, count(*) FROM E GROUP BY #class
But using count() + GROUP BY is extrimply slow combination.
While console command list classes works fast and return values for count of records in each class (field RECORDS), how to extract this counts via SQL query (or via OrientJS API)?
The main idea is find a way to:
Get list of all classes if database
Get count of records that stored in each class
Technical details
In OrientDB functions you have access to orient variable that have .getDatabase() method. And this method return JAVA ODatabaseDocumentTx class instance. This class provides the method .countClass(className) that returns the number of the records of the class className (method documentation) and it works realy fast.
Solution
Create function in OrientDB Studio with name "getClassCounts", language "javascript", idempotent: true:
var db = orient.getDatabase();
var classesRawInfo = db.getMetadata().getImmutableSchemaSnapshot().getClasses().toArray();
var classesList = {};
var i = classesRawInfo.length;
while(--i) {
var className = classesRawInfo[i].name;
classesList[className] = db.countClass(className);
}
return classesList;
Executing:
via SQL: SELECT getClassCounts()
I think it's not possible, also because it wouldn't so fast as in the console

Count in jpa without getting result [duplicate]

I like the idea of Named Queries in JPA for static queries I'm going to do, but I often want to get the count result for the query as well as a result list from some subset of the query. I'd rather not write two nearly identical NamedQueries. Ideally, what I'd like to have is something like:
#NamedQuery(name = "getAccounts", query = "SELECT a FROM Account")
.
.
Query q = em.createNamedQuery("getAccounts");
List r = q.setFirstResult(s).setMaxResults(m).getResultList();
int count = q.getCount();
So let's say m is 10, s is 0 and there are 400 rows in Account. I would expect r to have a list of 10 items in it, but I'd want to know there are 400 rows total. I could write a second #NamedQuery:
#NamedQuery(name = "getAccountCount", query = "SELECT COUNT(a) FROM Account")
but it seems a DRY violation to do that if I'm always just going to want the count. In this simple case it is easy to keep the two in sync, but if the query changes, it seems less than ideal that I have to update both #NamedQueries to keep the values in line.
A common use case here would be fetching some subset of the items, but needing some way of indicating total count ("Displaying 1-10 of 400").
So the solution I ended up using was to create two #NamedQuerys, one for the result set and one for the count, but capturing the base query in a static string to maintain DRY and ensure that both queries remain consistent. So for the above, I'd have something like:
#NamedQuery(name = "getAccounts", query = "SELECT a" + accountQuery)
#NamedQuery(name = "getAccounts.count", query = "SELECT COUNT(a)" + accountQuery)
.
static final String accountQuery = " FROM Account";
.
Query q = em.createNamedQuery("getAccounts");
List r = q.setFirstResult(s).setMaxResults(m).getResultList();
int count = ((Long)em.createNamedQuery("getAccounts.count").getSingleResult()).intValue();
Obviously, with this example, the query body is trivial and this is overkill. But with much more complex queries, you end up with a single definition of the query body and can ensure you have the two queries in sync. You also get the advantage that the queries are precompiled and at least with Eclipselink, you get validation at startup time instead of when you call the query.
By doing consistent naming between the two queries, it is possible to wrap the body of the code to run both sets just by basing the base name of the query.
Using setFirstResult/setMaxResults do not return a subset of a result set, the query hasn't even been run when you call these methods, they affect the generated SELECT query that will be executed when calling getResultList. If you want to get the total records count, you'll have to SELECT COUNT your entities in a separate query (typically before to paginate).
For a complete example, check out Pagination of Data Sets in a Sample Application using JSF, Catalog Facade Stateless Session, and Java Persistence APIs.
oh well you can use introspection to get named queries annotations like:
String getNamedQueryCode(Class<? extends Object> clazz, String namedQueryKey) {
NamedQueries namedQueriesAnnotation = clazz.getAnnotation(NamedQueries.class);
NamedQuery[] namedQueryAnnotations = namedQueriesAnnotation.value();
String code = null;
for (NamedQuery namedQuery : namedQueryAnnotations) {
if (namedQuery.name().equals(namedQueryKey)) {
code = namedQuery.query();
break;
}
}
if (code == null) {
if (clazz.getSuperclass().getAnnotation(MappedSuperclass.class) != null) {
code = getNamedQueryCode(clazz.getSuperclass(), namedQueryKey);
}
}
//if not found
return code;
}