NHibernate CreateSqlQuery and addEntity - mysql

The hibernate manual says this:
String sql = "SELECT ID as {c.id}, NAME as {c.name}, " +
"BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
"FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
List loggedCats = sess.createSQLQuery(sql)
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class).list()
Now, what I have is basically the same. I am return two of the same type per row. I am doing a select something like this:
SELECT {ctrl1.*}, {ctrl2.*} FROM tableA AS A
LEFT JOIN tableB AS ctrl1 ON (A.controlID = ctrl1.controlID AND ctrl1.controlOptionType = ? AND ctrl1.controlOptionValue = ?)
LEFT JOIN tableB AS ctrl2 ON (A.controlID = ctrl2.controlID AND ctrl2.controlOptionType = ? AND ctrl2.controlOptionValue = ?)
And then I addEntity("ctrl1", typeof(mycontrolclass) and
addEntity("ctrl1", typeof(mycontrolclass)
Which seems exactly the same to me as their example. But I get this exception:
"Could not execute query" and the inner exception is "Could not find specified column in results".
If I copy the sql in the exception(to which it has added "AS ctrl1_1_3_3_" etc) it works fine.
Thanks.

What exactly are you trying to do? I believe you might not need using either of them.
// Using HQL:
var motherId = 25;
var hql = "select c.birthDate, c.mother from Cat c where c.mother.Id = :motherId";
var result = Session.CreateQuery(hql)
.SetParameter("motherId", motherId)
.ToList();
// Using NHibernate.LINQ:
var result = (from cat in Session.Linq<Cat>()
where cat.Mother.Id == motherId
select new { cat.birthDate, cat.mother }).ToList();
HQL query examples.
LINQ for NHibernate examples.

I dealt with your problem just for studying purposes, because you will surely
have found a solution in the meanwhile, but the problem should not lie in
the query (which is ok), but in some mapping inconsistency or somewhere else
(perhaps Database).

Related

Linq to entity adding Where() clause breaks query

Using Microsoft SQL Entity Framework I've got a query where sometimes I have a filter condition and sometimes I don't, so I tried to do what I've shown below. If the condition is not null then instead of doing the query as expected it queries everything from the Org_Hierarchy table, and then queries everything from the Workers table, and then dies as that takes too long:
void SomeMethod(Func<PRT, bool> whereClause) {
IQueryable<PRT> query;
if (whereClause != null) {
query = PRT.Where(whereClause).AsQueryable();
} else {
query = PRT.AsQueryable();
}
var data = from prt in query
// LEFT OUTER JOIN Worker a ON prt.assigned_to = a.WWID
join a_join in Worker on prt.assigned_to equals a_join.WWID into a_grp
from a in a_grp.DefaultIfEmpty()
// LEFT OUTER JOIN Worker c ON prt.closed_by = c.WWID
join c_join in Worker on prt.closed_by equals c_join.WWID into c_grp
from c in c_grp.DefaultIfEmpty()
// LEFT OUTER JOIN Worker r ON prt.requestor = r.WWID
join r_join in Worker on prt.requestor equals r_join.WWID into r_grp
from r in r_grp.DefaultIfEmpty()
// LEFT OUTER JOIN Org_Hierarchy o ON prt.org3 = o.OrganizationHierarchyUnitCd AND o.OrganizationHierarchyUnitTreeLevelNbr = 3 AND o.Active = true
join o in Org_Hierarchy on prt.org3 equals o.OrganizationHierarchyUnitCd
select new PrtInput {
If I change the query and put something direct in there, just for testing, like where prt.id == Guid.NewGuid() right above the last line shown then the query returns in one second. What's the trick to be able to dynamically add a where clause to the query?
The above code is from LinqPAD which is why the normal "context" stuff is all missing.
I'm not sure , but i think you should use something like this :
Expression<Func<PRT ,bool>> whereClause
Insted of:
Func<PRT ,bool> whereClause
When you using Func<> , first fetch data from db to memory then filter data in memory ,but if you use Epression<> filter send to sql and return result.
Also for the better performnce you can use AsNoTracking() like this:
if (whereClause != null) {
query = PRT.Where(whereClause).AsQueryable().AsNoTracking();
} else {
query = PRT.AsQueryable().AsNoTracking();
}
When you only want run query on yout database without any Insert ,update or delete on result , it better use AsNoTracking.
I hope this answers your question.

issue with checking already existing values in table

I want to check of the values in my 3 textfield already exist in my table before proceeding further in my statement but it does not work in eclipse but work in heidisql? prepareStatement and resultset are properlt initislise at the top.
I already try using ? and preStatement.setString(1, get_status_update) but it gave me the same error result.
String get_status_update = stats_status_txta.getText();
String get_username= friend_username_txtf.getText();
String get_friendname= friend_list_txta.getText();
DB_connection db_connection = new DB_connection();
try{
if(get_username.length() < 3) {
JOptionPane.showMessageDialog(statusPanel,"You need to insert a username here","Post Lodge Status Error", JOptionPane.INFORMATION_MESSAGE);
} else if (get_status_update.length() < 3) {
JOptionPane.showMessageDialog(statusPanel,"Please insert the status update you wish to like","Post Lodge Status Error", JOptionPane.INFORMATION_MESSAGE);
} else {
String sql = " SELECT sut.status_update_id, up.user_id , fd.friend_id "
+ "FROM tb_logde_status_update as tsu "
+ "INNER JOIN status_update_tb as sut ON sut.status_update_id = tsu.status_update_id "
+ "INNER JOIN user_profile as up ON tsu.user_id = up.user_id "
+ "INNER JOIN friend_details as fd ON tsu.friend_id = fd.friend_id "
+ "WHERE sut.status_update_msg='"+get_status_update+"' AND up.username='"+get_username+"' AND fd.friend_username='"+get_friendname+"' ";
preStatement = db_connection.connect().prepareStatement(sql);
res = preStatement.executeQuery();
boolean send_logde_status = false;
while (res.next()) {
if(res.getString("status_update_msg").equalsIgnoreCase(get_status_update)
&& res.getString("username").equalsIgnoreCase(get_username)
&& res.getString("friend_username").equalsIgnoreCase(get_friendname)) {
JOptionPane.showMessageDialog(statusPanel, "Status update has already been like by you, choose another one!");
send_logde_status = true;
break; // Get out of the loop. No more need for it.
// Maybe the error is around here?
}
} ...
When I use the query directly from the database query it work!
SELECT sut.status_update_id, up.user_id , fd.friend_id
FROM tb_logde_status_update as tsu
INNER JOIN status_update_tb as sut ON sut.status_update_id = tsu.status_update_id
INNER JOIN user_profile as up ON tsu.user_id = up.user_id
INNER JOIN friend_details as fd ON tsu.friend_id = fd.friend_id
WHERE sut.status_update_msg="not hallo world" AND up.username="username" AND fd.friend_username="paul";
I am inserting the exactly values from my 3 textfields. I am getting the status_update_id, user_id, friend_id when i use the query from the database but not in my action listener button
Error: Column 'status_update_msg' not found.
Maybe the parameters are not exactly the same as the ones passed in the direct query, I would suggest the following:
Log the parameters values in console
Try using trim() and/or toLowerCase() if parameter values need to be in lower case only
Also, using setXXX() methods for preparedStatement is better approach than appending parameter values to a String query.

DQL And Equivalent SQL Not Returning Same Number Of Result Set

Here is my doctrine query running code:
$queryString = "SELECT ct, count(ct.id), IDENTITY(a.service) "
. "FROM ConnectionTriple ct "
. "JOIN ct.account_connection ac "
. "JOIN Account a WITH (a = ac.account_1 OR a = ac.account_2) "
. "GROUP BY a.service, ct.property, ct.value";
$query = $em->createQuery($queryString);
//echo $query->getSQL();
$results = $query->getResult();
echo count($results);
This above code is returning 2 results(final two from below screenshot) instead of 4(expected). But, when I run the equivalent SQL(got by $query->getSQL()) on phpmyadmin, it returns expected 4 rows which is as below:
Equivalent SQL Query:
SELECT u0_.id AS id0, u0_.value AS value1, u0_.status AS status2, u0_.flag AS flag3, count(u0_.id) AS sclr4, u1_.service_id AS sclr5, u0_.property_id AS property_id6, u0_.account_connection_id AS account_connection_id7 FROM usc_connection_triple u0_ INNER JOIN usc_account_connection u2_ ON u0_.account_connection_id = u2_.id AND (u2_.status = 1) INNER JOIN usc_service_subscriber u1_ ON ((u1_.id = u2_.account_1_id OR u1_.id = u2_.account_2_id)) WHERE (u0_.status = 1) AND (u1_.status = 1) GROUP BY u1_.service_id, u0_.property_id, u0_.value
PHPMyAdmin Result:
So, I guess, there is something wrong in result to object hydration by doctrine, I guess. Anyone has any idea why this might happen/possible solution?
My Doctrine version are:
"doctrine/dbal": "2.3.2",
"doctrine/orm": "2.3.2",
Update: I am certain about the hydration issue. Because, I tried with individual column retrieving and using scalar hydration:
$results = $query->getResult(\Doctrine\ORM\Query::HYDRATE_SCALAR);
This is returning perfectly. Which is expected number of rows, 4 and data as well.
I would say this is totally normal.
As you pointed it out, doctrine (default) hydration mode would represent the result set as an object graph.
An object graph always have a root object (in your case ConnectionTriple ct).
There are 2 ct in your result set (with id 1 and 2).
Doctrine object hydrator will be smart enough to return you and array
of 2 ConnectionTriple objects, each line containing the related data.
The scalar hydrator, howerver will simply return the raw resultset, without building a graph from it.

how to query several MYSQL tables in one statement

There are 30 tables(categories) all with the same structure storing news items with a siteID field to filter on a particular client.
The client select which tables(categories) they show by setting the field visible(tinyint) field to 1 or 0.
I have the following test MYSQL which works okay. I am using Applicationcraft.com so the syntax is different than standard MYSQL but you can see the query.
function _getAllData(cObj,p){
var result = [];
console.log('started');
selectObj=cObj.select().from('schoolNews').order('newsIDDESC').where('siteID=?',p.siteID);
result[0] = cObj.exec(selectObj);
selectObj=cObj.select().from('schoolDocs').order('newsIDASC').where('siteID=?',p.siteID);
result[1] = cObj.exec(selectObj);
return result;
}
So I have an array with the results of each table in result[0] & result[1].
So I created the following to :
function _getAllData(cObj,p){
var result = [];
console.log('started');
selectObj=cObj.select().from('schoolNews').order('newsIDDESC').where('siteID=?',p.siteID).where('visible=?',1);
result[0] = cObj.exec(selectObj);
selectObj=cObj.select().from('schoolDocs').order('newsIDASC').where('siteID=?',p.siteID).where('visible=?',1);
result[1] = cObj.exec(selectObj);
selectObj=Obj.select().from('schoolNews_copy').order('newsIDDESC').where('siteID=?',p.siteID).where('visible=?',1);
result[2] = cObj.exec(selectObj);
selectObj=cObj.select().from('schoolNews_copy').order('newsIDDESC').where('siteID=?',p.siteID).where('visible=?',1);
result[3] = cObj.exec(selectObj);
selectObj=cObj.select().from('schoolNews_copy').order('newsIDDESC').where('siteID=?',p.siteID;
result[4] = cObj.exec(selectObj).where('visible=?', 1);
upto result[30].
I have populated schoolNews_copy with 1000 records and run the query from my app.
I am getting a timed out error.
Is this because.
query the same table causes the problem.
This is the wrong approach all together.
If not what is the best approach.
Is there a way to query every table in a single statement and populate the results into an array named results.
So the result I need is an example array :
result[0] has data visible set to 1
result[1] has data visible set to 1
result[2] has data visible set to 0
I have now restructured the table as you said. And using joins can get all the info I need in one query.
SELECT * FROM categories INNER JOIN allNews on allNews.catID = categories.catID WHERE categories.visible = 1 AND categories.siteID = '+p.siteID;
MrWarby.

Linq to SQl - single result

I have been playing with the Linq to Sql and I was wondering if it was possible to get a single result out? For example, I have the following:
using(DataClassContext context = new DataClassContext())
{
var customer = from c in context.table
where c.ID = textboxvalue
select c;
}
And with this I need to do a foreach around the var customer but i know that this will be a single value! Anyone know how I could do a textbox.text = c.name; or something along that line?
Yes, it's possible.
using(DataClassContext context = new DataClassContext())
{
var customer = (from c in context.table
where c.ID = textboxvalue
select c).SingleOrDefault();
}
This way you get 1 result or null if there isn't any result.
You can also use Single(), which throws an exception when there isn't a result.
First() will give you only the first result found, where Last() will give you only the last result, if any.
Here's an Overview of all Enumerable methods.
var customer = context.table.SingleOrDefault(c => c.ID == textboxvalue);