How NHibernate cache native queries? - nhibernate

I have native sql query using in global NHibernate common session like
string sql = #"update Accounts
set vchBranch = :branch,
bitIsActive = :isActive,
bitIsVisible = :isVisible
where bintId = :id";
ISQLQuery sqlQuery = HibernateUtil.GetCurrentSession().CreateSQLQuery(sql);
sqlQuery.SetBoolean("isActive", account.IsActive);
sqlQuery.SetBoolean("isVisible", account.IsVisible);
sqlQuery.SetInt64("id", account.Id);
sqlQuery.ExecuteUpdate();
Is NHibernate cache result of this query?

I found answer. It caching result object in Nhibernate session.
In mapping XML-file I found references to model objects.

Related

How to get sys.databases or sys.tables from sql in ef core

I have a question what I couldn't resolve it for 2 days. I'm working on .NET Core 2.2 by the way and thats why I'm using Entity Framework Core.
I need to get sys.databases, sys.tables and sys.columns from sql but I couldn't reach them whatever I tried.
Someone advised me; Create a Stored Procedure and get them this way.
var result = dbcontext.Databases.FromSql("sp_GetDatabases").ToList();
I've tried but didn't reach because I don't want specific data in context.
This only applies to data in DbContext.
So I didn't find how to get them. Need some help!
var connectionDb = _context.Database.GetDbConnection();
if (connectionDb.State.Equals(ConnectionState.Closed))
connectionDb.Open();
object data = null;
using (var command = connectionDb.CreateCommand())
{
command.CommandText = #"Your query here";
data = command.ExecuteScalar();
}
Bit too late. But might help someone else out.

NHibernate - How to log Named Parameterised Query with parameter values?

I have a parameterised named Query like this :
Query moveOutQuery = session.createSQLQuery(moveOutQueryStr.toString())
.addEntity(MyClass.class)
.setParameter("assignmentStatus", Constants.CHECKED_OUT)
I want to see the actual SQL query with parameters filled in. However while debugging I only get the following query:
Select * from my_assignment WHERE assignment_status in ( :assignmentStatus )
Why isn't the assignmentStatus being substituted for its real value?
Why isn't the assignmentStatus being substituted for its real value?
This is because NHibernate use query parameters to input values. This is efficient in many cases and also helpful against SQL Injection attack. Parameters are sent separately. You can find them at the bottom if SQL is logged as explained below.
You may log each SQL to file as explained below.
This is implemented through log4net.dll; you need to add reference.
Add namespaces as below:
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
Configure log4net in NHibernate as below:
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.Root.RemoveAllAppenders();
FileAppender fileAppender = new FileAppender();
fileAppender.Name = "NHFileAppender";
fileAppender.File = logFilePath;
fileAppender.AppendToFile = true;
fileAppender.LockingModel = new FileAppender.MinimalLock();
fileAppender.Layout = new PatternLayout("%d{yyyy-MM-dd HH:mm:ss}:%m%n%n");
fileAppender.ActivateOptions();
Logger logger = hierarchy.GetLogger("NHibernate.SQL") as Logger;
logger.Additivity = false;
logger.Level = Level.Debug;
logger.AddAppender(fileAppender);
hierarchy.Configured = true;
You also need to set ShowSql while configuration as below:
configuration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true");
configuration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "true");
You need to call this code once at startup of your application. Output log includes values of parameters as well.
Following is the code:
session.CreateSQLQuery("SELECT * FROM MyEntity WHERE MyProperty = :MyProperty")
.AddEntity(typeof(MyEntity))
.SetParameter("MyProperty", "filterValue")
.UniqueResult<MyEntity>();
Following is the logged query:
2020-01-09 14:25:39:
SELECT
*
FROM
MyEntity
WHERE
MyProperty = #p0;
#p0 = 'filterValue' [Type: String (4000:0:0)]
As you can see, parameter value filterValue is listed at the bottom.
This works for all query APIs like IQueryOver, IQuery, ISQLQuery etc.
This logs both success and failed statements. You can play with FileAppender and Logger class to meet your additional requirements.
Also refer PatternLayout from documentation. More details can also be found here, here and here. This Q/A discusses the same.
Following Q/A may also help:
Get executed SQL from nHibernate
Using log4net to write to different loggers
How to log SQL calls with NHibernate to the console of Visual Studio?
As you see, this logs the parameter values at bottom of the query. If you want those logged embedded in the query, please refer to this article.

org.hibernate.exception.SQLGrammarException: could not execute query?

I got this exception when i try to get the list using NamedQuery:
org.hibernate.exception.SQLGrammarException: could not execute query
Below I mentioned code:
Entity Class Code:
#Table(name = "tbl_users")
#XmlRootElement
#NamedQueries({#NamedQuery(name = "TblUsers.findAll", query = "SELECT t FROM TblUsers t")});
DAO implement Code:
org.hibernate.Query query = session.getNamedQuery("TblUsers.findAll");
List list = query.list();
Please provide solution for this exception.
Was facing same issue for a while and figured out that the problem was due to the Table name being different from the class(or Entity) name in the database. Added the #Table(name = actual_table_name) annotation and it worked.
Get the SQL query that Hibernate is generating (using hibernate.show_sql or, preferably, Hibernate's SQL logging), and execute it against the database yourself. That will most likely help steer you in the right direction.
Try this one it could work.
It Perfectly worked for me.
1) Class level annotation.
#NamedQuery(name="UserDetails.byId" , query="from UserDetails where userId = ?")
2) Get record using NamedQuery
Query qry2 = sf.getCurrentSession().getNamedQuery("USER_DETAILS.byName") ;
qry2.setString(0, "Angad Bansode");
List<UserDetails> user = qry2.list();
for (UserDetails userDetails : user) {
System.out.println("User Details by named native query name = " + userDetails.getUserName() + ", aadhaar no = " + userDetails.getAadharNo());
}
seems like this question is little old but any way once i added below line to hibernate config files it worked for me.
<property name="show_sql">true</property>
For me it was missing access to sequence for auto-increment primary key. After adding this error was resolved.
GRANT USAGE, SELECT ON ALL
SEQUENCES IN SCHEMA public
TO "${user-name}";;

Using Raw SQL with Doctrine

I have some extremely complex queries that I need to use to generate a report in my application. I'm using symfony as my framework and doctrine as my ORM.
My question is this:
What is the best way to pass in highly-complex sql queries directly to Doctrine without converting them to the Doctrine Query Language? I've been reading about the Raw_SQL extension but it appears that you still need to pass the query in sections (like from()). Is there anything for just dumping in a bunch of raw sql commands?
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute(" -- RAW SQL HERE -- ");
See the Doctrine API documentation for different execution methods.
Yes. You can get a database handle from Doctrine using the following code:
$pdo = Doctrine_Manager::getInstance()->getCurrentConnection()->getDbh();
and then execute your SQL as follows:
$query = "SELECT * FROM table WHERE param1 = :param1 AND param2 = :param2";
$stmt = $pdo->prepare($query);
$params = array(
"param1" => "value1",
"param2" => "value2"
);
$stmt->execute($params);
$results = $stmt->fetchAll();
You can use bound variables as in the above example.
Note that Doctrine won't automatically hydrate your results nicely into record objects etc, so you'll need to deal with the results being returned as an array, consisting of one array per row returned (key-value as column-value).
I'm not sure what do you mean saying raw SQL, but you coud execute traditional SQL queries this way:
...
// $this->_displayPortabilityWarning();
$conn = Doctrine_Manager::connection();
$pdo = $conn->execute($sql);
$pdo->setFetchMode(Doctrine_Core::FETCH_ASSOC);
$result = $pdo->fetchAll();
...
The following method is not necsessary, but it shows a good practice.
protected function _displayPortabilityWarning($engine = 'pgsql')
{
$conn = Doctrine_Manager::connection();
$driver = $conn->getDriverName();
if (strtolower($engine) != strtolower($driver)) {
trigger_error('Here we have possible database portability issue. This code was tested on ' . $engine . ' but you are trying to run it on ' . $driver, E_USER_NOTICE);
}
}
You can also use Doctrine_RawSql(); to create raw SQL queries which will hydrate to doctrine objects.
It should be noted, that Doctrine2 uses PDO as a base, thus I would recommend using prepared statements over plain old execute.
Example:
$db = Doctrine_Manager::getInstance()->getCurrentConnection();
$query = $db->prepare("SELECT `someField` FROM `someTable` WHERE `field` = :value");
$query->execute(array('value' => 'someValue'));
Symfony insert raw sql using doctrine.
This in version Symfoney 1.3
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute($query);

How should I use navigation properties while writing a query using eSQL?

I am trying to write a query using eSQL wherein my entity has got navigation properties. I am not able to include these navigation properties in the query, even though in Linq to SQL we have this (Include method).
How will it be possible in eSQL?
Like so:
string esql = "Select value e from EFEntities.MyDataEntity as e";
ObjectQuery<Data.MyDataEntity> query = c.
CreateQuery<Data.MyDataEntity>(esql).
Include("MyNavigationProperty");
List<Data.MyDataEntity> entities = query.ToList();