Goal:
Make the stored procedure to be working with nhibernate.
Problem:
I retrieve an error message:
could not execute query
[ exec sp_retrieveAllProductList #p0 ]
Name:Produkt_kategori - Value:Dryck
[SQL: exec sp_retrieveAllProductList #p0]
What is the problem in the source code?
Info:
- Using VS 2013.
For AliasToBean to work, the returned column names (and their types) must match exactly the properties on the class to convert to.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="data_layer" namespace="data_layer">
<sql-query name="sp_retrieveAllProductList">
<return-scalar column="Produkt" type="string" />
<return-scalar column="Produkt_kategori" type="string" />
exec sp_retrieveAllProductList :Produkt_kategori
</sql-query>
</hibernate-mapping>
Never forget to change the column to the right value.
Related
I have some XML snippets that I store via NHibernate (3.2.0.4000) in a SQL Server database. The table column is defined as XML. Storing and Updating of the XML is working, but in the database I am missing the first node with the encoding and version information.
C# object, inner XML:
<?xml version="1.0" encoding="utf-16"?>
<RsSn>
<Layermapping xmlns="someNamespace">
<Layer layerName="0" layerDescription="5876548" />
<Layer layerName="1" layerDescription="5876549" />
</Layermapping>
</RsSn>
SQL Server Profiler when the data is inserted:
declare #p6 xml
set #p6=convert(xml,
N'<RsSn><Layermapping xmlns="someNamespace">
<Layer layerName="0" layerDescription="5876548"/>
<Layer layerName="1" layerDescription="5876549"/>
</Layermapping>
</RsSn>'
)
The <?xml version="1.0" encoding="utf-16"?> element is missing!
Content of SQL server column (via SSMS studio):
<RsSn>
<Layermapping xmlns="someNamespace">
<Layer layerName="0" layerDescription="5876548" />
<Layer layerName="1" layerDescription="5876549" />
</Layermapping>
</RsSn>
NHibernate Configuration (part of mapping file)
<class name="SnippetEntity" table="tblSnippet">
<id name="SnippetPK" column="SnippetPK" type="Int64">
<generator class="native" />
</id>
<property name="ResourceData" column="ResourceData" type="NHibernate.Type.XmlDocType"/>
</class>
I am not allowed to update the NHibernate assembly.
Is this the correct type that I am using in the mapping file?
Is there some other configuration I have to use so the document is stored "well formed" in the database?
The top <?xml version="1.0" encoding="utf-16"?> construct is called XML prolog. It is not mandatory to have it. XML is well-formed without it.
SQL Server stores XML as Unicode (utf-16). There is no other encoding. That's why SQL Server strips the prolog when it exists in XML.
I'm trying to do a fairly simple insert using NHibernate into a SqlCe database, but it seems that NHibernate is generating wrong table name. It throws GenericADOException with the following details:
could not insert:
[WebLibrary.Models.Category#400a532d-f62e-4faf-978b-a29c00d4de46]
[SQL: INSERT INTO WebLibrary.Models_Categories (Title, Slug, DateCreated,
LastModified, CreatedBy, LastModifiedBy, ParentId, Id) VALUES (?, ?,
?, ?, ?, ?, ?, ?)]
Here is the mapping:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping schema="WebLibrary.Models" assembly="WebLibrary" namespace="WebLibrary.Models" xmlns="urn:nhibernate-mapping-2.2">
<class name="Category" table="Categories">
<id name="Id" type="Guid">
<column name="Id" not-null="true" />
<generator class="guid.comb" />
</id>
...
</class>
</hibernate-mapping>
And here is the configuration:
var cfg = new Configuration();
cfg.DataBaseIntegration(c =>
{
c.Dialect<MsSqlCe40Dialect>();
c.ConnectionString =
"Data Source=|DataDirectory|\\library.sdf;Persist Security Info=False;";
})
.AddAssembly(typeof(NHibernateConfiguration).Assembly);
As you can see NHibernate is using the full qualified name of the class as the name of the table.
I'm using NHibernate 3.3.1.4000 with SqlCe 4.0.
What am I missing?
Your mapping contains a schema attribute. Remove that.
Adding a schema will prefix the table with the schema name.. which isn't required for tables in the default schema.
I have an object of type Video. I am storing Videos in my database, but I want each video entry to be unique. Uniqueness is determined by an 11-digit string provided by the client.
As such, I've generated this Video.hbm.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Streamus" namespace="Streamus.Domain">
<class name="Video" table="[Videos]" lazy="false" mutable="false">
<id name="Id" length="11" type="String" />
<property name="Title" not-null="true" />
<property name="Duration" not-null="true" />
<property name="Author" not-null="true" />
</class>
</hibernate-mapping>
I have no intention of deleting or updating any entries to this table. So, I've tagged my class as immutable.
Now, I thought this was a pretty good way of going about things, but I am experiencing issues with cascade-updating from a parent object. Because my ID is generated client-side, and I do not leverage a second identifier, NHibernate is unable to reliably determine whether a Video needs to be Inserted or Updated (note that it should never update due to being immutable.)
Something like:
Video video = new Video("s91jgcmQoB0", "Tristam - Chairs", 219, "MeoMix");
new VideoManager().Save(video);
// Create a new PlaylistItem and write it to the database.
string title = video.Title;
PlaylistItem playlistItem = new PlaylistItem(title, video);
Playlist.AddItem(playlistItem);
PlaylistManager.SavePlaylistItem(playlistItem);
where PlaylistItem's hbm.xml references Video as:
<many-to-one name="Video" column="VideoId" not-null="true" cascade="save-update" />
The above code generates a NonUniqueObjectException. This is because the VideoManager works with the Video in one session, closes it, then PlaylistManager re-references the same Video in a new Session, but NHibernate can't accomodate because it doesn't have good IDs to go off of.
Removing the option of cascade="save-update" fixes the issue, but then I don't get the benefit of having my Video object created implicitly in the database by NHibernate. Instead, I would have to manually save the Video object and, afterwards, save the PlaylistItem object. This is clearly not ideal.
So, I'm wondering -- should I be assigning a GUID to my Video object? If so, how can I enforce the fact that I only wish to have unique Video entries in my table where uniqueness is defined by the 11 digit string ID?
Let me know if I can provide any more information to make this more clear.
First of all modify your ID section in you video.hbm.xml to have an "assigned" generator
<id name="id" ....>
<generator class="assigned" />
</id>
That tells nhibernate that ur IDs are manually generated from the client.
Also having ur same object being manipulated by multiple session will cause consistency errors. So either use a unique session for your batch of actions or make sure ur object is properly tracked in all sessions by using session.Merge
I have Canine and CanineHandler objects in my application. The CanineHandler object has a PersonID (which references a completely different database), an EffectiveDate (which specifies when a handler started with the canine), and a FK reference to the Canine (CanineID).
Given a specific PersonID, I want to find all canines they're currently responsible for. The (simplified) query I'd use in SQL would be:
Select Canine.*
from Canine
inner join CanineHandler on(CanineHandler.CanineID=Canine.CanineID)
inner join
(select CanineID,Max(EffectiveDate) MaxEffectiveDate
from caninehandler
group by CanineID) as CurrentHandler
on(CurrentHandler.CanineID=CanineHandler.CanineID
and CurrentHandler.MaxEffectiveDate=CanineHandler.EffectiveDate)
where CanineHandler.HandlerPersonID=#PersonID
Edit: Added mapping files below:
<class name="CanineHandler" table="CanineHandler" schema="dbo">
<id name="CanineHandlerID" type="Int32">
<generator class="identity" />
</id>
<property name="EffectiveDate" type="DateTime" precision="16" not-null="true" />
<property name="HandlerPersonID" type="Int64" precision="19" not-null="true" />
<many-to-one name="Canine" class="Canine" column="CanineID" not-null="true" access="field.camelcase-underscore" />
</class>
<class name="Canine" table="Canine">
<id name="CanineID" type="Int32">
<generator class="identity" />
</id>
<property name="Name" type="String" length="64" not-null="true" />
...
<set name="CanineHandlers" table="CanineHandler" inverse="true" order-by="EffectiveDate desc" cascade="save-update" access="field.camelcase-underscore">
<key column="CanineID" />
<one-to-many class="CanineHandler" />
</set>
<property name="IsDeleted" type="Boolean" not-null="true" />
</class>
I haven't tried yet, but I'm guessing I could do this in HQL. I haven't had to write anything in HQL yet, so I'll have to tackle that eventually anyway, but my question is whether/how I can do this sub-query with the criterion/subqueries objects.
I got as far as creating the following detached criteria:
DetachedCriteria effectiveHandlers = DetachedCriteria.For<Canine>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.Max("EffectiveDate"),"MaxEffectiveDate")
.Add(Projections.GroupProperty("CanineID"),"handledCanineID")
);
but I can't figure out how to do the inner join. If I do this:
Session.CreateCriteria<Canine>()
.CreateCriteria("CanineHandler", "handler", NHibernate.SqlCommand.JoinType.InnerJoin)
.List<Canine>();
I get an error "could not resolve property: CanineHandler of: OPS.CanineApp.Model.Canine". Obviously I'm missing something(s) but from the documentation I got the impression that should return a list of Canines that have handlers (possibly with duplicates). Until I can make this work, adding the subquery isn't going to work...
I've found similar questions, such as Only get latest results using nHibernate but none of the answers really seem to apply with the kind of direct result I'm looking for.
Any help or suggestion is greatly appreciated.
Joining to a derived table, CurrentHandler in your example, won't work in HQL the last time I checked. Try mapping a stored procedure that lets you write whatever SQL you like. Here's what a mapped stored procedure looks like:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="S2.BP.NHSupport" namespace="S2.BP.Model">
<sql-query name="spGoGetMyDogs" callable="true">
<return-scalar column="PersonID" type="int" />
exec spGoGetMyDogs #PersonID=:personID
</sql-query>
</hibernate-mapping>
Then you can pass your PersonID parameter in and have NH map the results back to your objects with a transformer like so:
public IEnumerable<Canine> LetTheDogsOut(int personID) {
return nhSession.GetNamedQuery("spGoGetMyDogs")
.SetInt32("personID", personID)
.SetResultTransformer(Transformers.AliasToBean(typeof(Canine)))
.List<Canine>();
}
I'm trying to solve pretty easy problem. I want to establish connection to 2 totally different databases ( but both mysql ). Now I tried to solve this by creating multiple config files and then creating multiple sessions. Everything works until I reached relations.
I have 2 tables in 2 databases:
db1
- News
db2
- News_Authors
I added News to db1 config and News_Authors to db2 config. When I try to build simple one-to-one relation error, I receive:
An association from the table songs refers to an unmapped class: db1.News_Authors
News.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="project.News, project" table="news" lazy="false">
<id name="id" column="id" type="integer" length="11">
<generator class="native" />
</id>
<property name="title" type="String" length="255" />
<property name="authorid" type="integer" length="5" />
<one-to-one name="NewsAuthor" cascade="all-delete-orphan" lazy="proxy" column="authorid" unique="true" />
</class>
</hibernate-mapping>
News_Authors.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="project.News_Authors, project" table="news_authors" lazy="false">
<id name="id" column="id" type="integer" length="11">
<generator class="native" />
</id>
<property name="name" type="String" length="255" />
</class>
</hibernate-mapping>
config
I added this to enable mappings. Now If I set both in one config files, everything works...
<mapping resource="project.News.hbm.xml" assembly="project" />
So how could I during creating of session also "notify" nhibernate that I have multiple sessions? Or should I pick totally another approach?
One other possible solution would be to create views in one of the sql server databases to reference the tables in the other. Views map just like tables and its easy to do a view that returns something like:
select * from db2.News_Authors
in the db1 database.
this way you would only need a single .hbm.xml file that maps to one of the two databases.
Hope this helps,
-Max
What you are after is not multiple sessions but multiple session factories. See this for more details.
The key here is that you don't have to initialize your session factory through config file - you can do it programatically. And it's just a step to have two session factories.