Using NHibernate to insert into view - nhibernate

If one would want to insert into a view, what would be required to setup on NHibernate to allow this.
Neither
<generator class="identity" />
nor
<generator class="native" />
allows insert.
Error I get when I try this is either "Null id" or "Null identifier".

You can not insert, update or delete from a view even with regular SQL commands, nor with NHiberanate. Views are designed for read only purposes.
You should model your class from the original tables in a similar fashion as the view and then you could do any CRUD operation on it.

I have never done this but have you tried assigned:-
<generator class="assigned" />
Any modifications, including UPDATE, INSERT, and DELETE statements,
must reference columns from only one base table.
See here MSDN for more info
And there is one more thing if you use assigned, you have to explicitly specify to NHibernate if the object should be saved or updated by calling either the Save() or Update() method of the ISession.

Related

Liquibase changeSet with failOnError="false" are always ran?

I'm trying to execute the following changeSet in liquibase which should create an index. If the index doesn't exist, it should silently fail:
<changeSet failOnError="false" author="sys" id="1">
<createIndex unique="true" indexName="key1" tableName="Table1">
<column name="name" />
</createIndex>
</changeSet>
So far, so good. The Problem is, that this changeSet doesn't get logged into DATABASECHANGELOG table and is therefor executed every time liquibase runs. According to the liquibase documentation and e.g. this answer from Nathen Voxland i thought that the changeset should be marked as ran in the DATABASECHANGELOG table. Instead it isn't logged at all and as i said before executed every time liquibase runs (and fails everytime again).
Am i missing something?
(I'm using MySQL as DBMS)
In the answer given by Nathen Voxland, he recommended the more correct approach of using a precondition to check the state of the database, before running the changeset.
It seems to me that ignoring a failure is a bad idea.... Means you don't fully control the database configuration.... The "failOnError" parameter allows liquibase to continue. Wouldn't it be a bad idea for a build to record a changset as executed, if in fact it didn't because an error occurred?

Indexed views & Nhibernate - NOEXPAND Hint?

Is it possible to configure NHibernate to issue the NOEXPAND hint when it executes a select statement against an indexed view? SQL Server always skips the views and goes straight to the base tables when executing queries unless the hint is used.
Here is a hack I tried and it worked. Just added (NOEXPAND) to the "table" name.
<class name="ClassName" mutable="false" table="vw_ViewName (NOEXPAND)">
...
</class>

Many-to-many and HQL batch delete

I have two entities with many-to-many relationship defined on them.
<set name="TreasuryCodes" table="ServiceProviderAccountTreasuryCode" lazy="true" cascade="all">
<key column="ServiceProviderAccountId" />
<many-to-many column="TreasuryCodeId" class="TreasuryCode" />
</set>
<set name="ServiceProviderAccounts" table="ServiceProviderAccountTreasuryCode" lazy="true" inverse="true" cascade="all">
<key column="TreasuryCodeId" />
<many-to-many column="ServiceProviderAccountId" class="ServiceProviderAccount" />
</set>
Now I want to delete all ServiceProviderAccounts by ServiceProviderId. I write this code:
public void DeleteAllAccount(int serviceProviderId)
{
const string query = "delete ServiceProviderAccount spa where spa.ServiceProvider.Id = :serviceProviderId";
repository.Session.CreateQuery(query)
.SetInt32("serviceProviderId", serviceProviderId)
.ExecuteUpdate();
repository.Session.Flush();
}
and I receive this exception:
Test method Test.ServiceRepositoryTest.DeleteAllAccountTest threw exception:
NHibernate.Exceptions.GenericADOException: could not execute update query[SQL: delete from ServiceProviderAccount where ServiceProviderId=?] ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FKBC88A84CB684BF79". The conflict occurred in database "Test", table "dbo.ServiceProviderAccountTreasuryCode", column 'ServiceProviderAccountId'.
The statement has been terminated.
I'm confused, as I have defined cascade on the entity, shouldn't nhibernate remove rows from ServiceProviderAccountTreasuryCode?
UPDATE
ok, looks like ExecuteUpdate is not looking for NHibernate cascade, probably because it's not loading entities before deleting it? Anyway is there any other way to delete from ServiceProviderAccountTreasuryCode table and then from ServiceProviderAccounts via HQL? I know I can use cascades on database, but I want to avoid that. What I want is to delete rows from many-to-many association table by HQl. Is it possible? Or I should use plain SQL?
looks like you have a referential integrity problem i.e a foregin key relation ship where the id that you are deleting is being referenced somewhere else and that table will end up referencing nothing. if that is what you want to do then you can run the Truncate command but I am not sure why you will do that..
I would suggest you do a normal delete i.e using the nhibernate session and Linq like below:
foreach(var sessionProvider in Session.Linq<ServiceProviderAccount >().Where(x=>x.ServiceProvider.Id==servinceProviderId))
Session.Delete(sessionProvider);
Now note this is not at all a bad way to do your deletion as they are not fired against the dB immediately and is part of the Session till your transaction is committed and this should handle your referential integrity problems if your mappings are defined crrectly.
Hope this works..
Looks like it doesn't obey the cascading. HQL batch operations for update/delete is relatively new, and translate more or less directly to SQL. I believe that you must keep track of the related tables as well.
If you only delete single entities then the batch-delete doesn't do you much good. In order for NHibernate to actually take cascading into account, it must load the actual entitity, which you don't with your example.
I asked a similar question, the answer I got might interest you
Remove entity in NHibernate only by primary key

NHibernate not dropping foreign key constraints

I'm new to NHibernate, so this is probably my mistake, but when I use:
schema.Create(true, true);
I get:
SchemaExport [(null)]- There is already an object named 'XXX' in the database.
System.Data.SqlClient.SqlException: There is already an object
named 'XXX' in the database.
I grabbed the SQL code nHibernate was using, ran it directly from MSSMS, and recieved similar errors. Looking into it, the generated code is not properly dropping the foreign key constraints. The drop looks like this:
if exists (select 1 from sysobjects where id = OBJECT_ID(N'dbo[FK22212EAFBFE4C58]')
AND parent_obj = OBJECT_ID('YYY'))
alter table dbo.YYY drop constraint FK22212EAFBFE4C58
Doing a "select OBJECT_ID(N'dbo[FK22212EAFBFE4C58]')" I get null. If I take out the "dbo" (i.e. "select OBJECT_ID(N'[FK22212EAFBFE4C58]')") then the ID is returned.
So, my question is, why is nHibernate adding the dbo, and why does that prevent the object from being returned (since the table owning the constraint is dbo.XXX)
One of my mapping files:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="CanineApp.Model" assembly="CanineApp.Model" xmlns="urn:nhibernate-mapping-2.2">
<class name="MedicalLog" table="MedicalLog" schema="dbo">
<id name="MedicalLogID" type="Int64">
<generator class="identity" />
</id>
<property name="InvoiceAmount" type="Decimal" not-null="true" />
...
<many-to-one name="Canine" class="Canine" column="CanineID" not-null="true" fetch="join" />
<many-to-one name="TreatmentCategory" class="TreatmentCategory" column="TreatmentCategoryID" not-null="true" access="field.camelcase-underscore" />
</class>
</hibernate-mapping>
Answer: .
It's probably a bug. There was an entry for this exact issue for SQL Server 2005. It doesn't appear to have been flagged for SQL 2000, so I'll either create a bug report or fix it.

How to execute an update via SQLQuery in Hibernate

I need to update a joined sub-class. Since Hibernate doesn't allow to update joined sub-classes in hql or named-query I want to do it via SQL. I also can't use a sql named-query because updates via named-query are not supported in Hibernate.
So I decided to use a SQLQuery. But Hibernate complaints about not calling addScalar():
org.hibernate.QueryException: addEntity() or addScalar() must be called on a sql query before executing the query.
Are updates returning the number of rows affected and how is named that column?
Are there any other ways to do an update on a joined sub-class in hibernate?
Here is a brief example of what i'm trying to do:
<hibernate-mapping>
<class name="example.NiceClass" table="NICE_CLASS">
<meta attribute="class-code"></meta>
<id name="id" type="java.lang.Long">
<column name="NICE_CLASS_ID" precision="8" />
<generator class="sequence">
<param name="sequence">NICE_CLASS_SEQ</param>
</generator>
</id>
</class>
</hibernate-mapping>
<hibernate-mapping package="example">
<joined-subclass name="SubJoinedClass" table="SUB_JOINED_CLASS"
extends="NiceClass">
<key column="NICE_CLASS_ID" foreign-key="NICE_JOINED_ID_FK"/>
<property name="name" type="string" not-null="false">
<column name="NAME" >
<comment>name</comment>
</column>
</property>
</joined-subclass>
</hibernate-mapping>
Thanks in advance!
So I want to do a:
update SubJoinedClass set name = 'newName'
How do you execute the update query ? What method do you call to execute it ? Do you call 'ExecuteUpdate' ?
And why do you think that you cannot execute an update query on a subclass using HQL ? AFAIK, it is possible.