I am having some problem configuring NHibernate to retrieve data in my MVC 4 application.
To keep things simple I have configured all code in the Index method.
Here is code for my Category controller :
and here is my configuration in web.config :
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="NHibernate.Test">
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<property name="connection.connection_string">
Data Source=.;Initial Catalog=UsingNH;uid=myuid;Password=mypwd
</property>
<property name="adonet.batch_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="use_outer_join">true</property>
<property name="command_timeout">60</property>
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
</session-factory>
</hibernate-configuration>
Mapping file for Category is
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="nhibernate-mapping-2.2" namespace="UsingNHibernate.Models" assembly="UsingNHibernate">
<class name="Category" table="Categories" lazy="false">
<id name="Id" columnId="Id" unsaved-value="0">
<generator class="native" />
</id>
<property name="Name">
<column name="Name" data-type="varchar(50)" not-null="true" />
</property>
</class>
</hibernate-mapping>
and the Category table schema is
CREATE TABLE [dbo].[Categories](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
) ON [PRIMARY]
The problem is that the program compiles and runs well but does not return any category.
The code
var lst = (List<Category>)criterion.List<Category>();
returns 0 items (verified in debugger).
Is there any problem in my configuration or Mapping files?
Comment if additional info is required.
Thanks.
If no mappings are defined, nhibernate will simply fail silently and return an empty list if you query a list of entities.
I guess you do not copy over the mapping files to your bin directory. Mark the mapping files to be copied (via properties).
I changed the Build Action Property of the hbm mapping file to Embedded Resource,
then I can get the data.
(It's same way as the OP's comment, but I post it as an answer to be easier noticed.)
Related
I have a tree structure mapped to the data base in a table like this:
UID numeric(18, 0)
NodeUID varchar(50)
Text nvarchar(50)
TreeLevel int
ParentUID varchar(50)
OrderInLevel int
IsLeaf bit
It is an old table and I cannot change it so bear with me...
The NodeUID is a GUID.
the ParentUID column is mapped to the NodeId of a different row.
A root node has a value of "0" in its ParentUID column.
I am trying to map the Tree with NHibernate like this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="BasicFW.Core.Domain.NavigationTree.UsersNavigationTreeNode, BasicFW.Core" table="bDoxTreeNodes" lazy="false" schema="bDox.dbo">
<id name="NodeUId">
<column name="NodeUID"/>
<generator class="assigned"/>
</id>
<property name="Text">
<column name="Text"/>
</property>
<property name="TreeLevel">
<column name="TreeLevel"/>
</property>
<property name="IsLeaf">
<column name="IsLeaf"/>
</property>
<many-to-one name="Parent" class="BasicFW.Core.Domain.NavigationTree.UsersNavigationTreeNode, BasicFW.Core" column="ParentUID" not-found="ignore"/>
<bag name="Children" lazy="false" order-by="OrderInLevel ASC" cascade="all-delete-orphan" inverse="true">
<key column="ParentUID"/>
<one-to-many class="BasicFW.Core.Domain.NavigationTree.UsersNavigationTreeNode, BasicFW.Core" />
</bag>
</class>
</hibernate-mapping>
The thing is that when I try to update a node ( and a root node in specifies ) the Parent property is null and so NHibernate try`s to Update the ParentUID column to null, and so it failles since to column will not accept null.
thanks
Can you create a trigger for that table? If yes, you could perhaps create a trigger that fires before update/insert. Something like:
create trigger TreeNode_before before insert, update
on TreeNode
referencing NEW as _new
for each row
begin
if _new.ParentUID is null then
set _new.ParentUID = '0';
end if;
end;
Edit: An alternative would be using an interceptor. I have not used that myself but according to the following question it should work in your case, too.
Edit: fixed the link.
NHibernate write value = NULL when ID < 0
I have found the correct mapping that worked, here is the mapping for my tree.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="BasicFW.Core.Domain.NavigationTree.UsersNavigationTreeNode, BasicFW.Core" table="TreeNodes" lazy="false" >
<id name="NodeID">
<column name="NodeUID"/>
<generator class="assigned"/>
</id>
<property name="Text">
<column name="Text"/>
</property>
<property name="TreeLevel">
<column name="TreeLevel"/>
</property>
<property name="ParentID" >
<column name="ParentUID" />
</property>
<property name="IsLeaf">
<column name="IsLeaf"/>
</property>
<many-to-one name="Parent" class="BasicFW.Core.Domain.NavigationTree.UsersNavigationTreeNode, BasicFW.Core" column="ParentUID" not-found="ignore" update="false" insert="false"/>
<bag name="Children" lazy="false" order-by="OrderInLevel ASC" inverse="true" cascade="all-delete-orphan">
<key column="ParentUID"/>
<one-to-many class="BasicFW.Core.Domain.NavigationTree.UsersNavigationTreeNode, BasicFW.Core"/>
</bag>
</class>
</hibernate-mapping>
I have disabled the update and insert in the Parent property.
I have at my SQL Server 2000 Database a column with type Image. How can I map it into NHibernate?
We used BinaryBlob on the mapping config file, and byte[] on the property.
Below is the sample code that i have used to map an image field. Where BlogImage was a column of Image Datatype mapped to byte type property BlogImage. length="2147483647" was used to ensure copy of full image in to database as nhibernate some times limit the max size of data that is going to be inserted.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="EAS.MINDSPACE.Infrastructure.Business.Entities.BlogMaster,EAS.MINDSPACE.Infrastructure.Business.Entities" lazy="false" table="BlogMaster" schema="dbo" >
<id name="BlogId" column="BlogId">
<generator class="native" />
</id>
<property name="BlogData" column="BlogData" />
<property name="BlogImage" column="BlogImage" length="2147483647" />
<property name="UserId" column="UserId" />
<property name="CreatedByName" column="CreatedBy" />
<property name="CreatedOn" column="CreatedOn" />
<property name="ReplyCount" column="ReplyCount" />
</class>
</hibernate-mapping>
NHibernate 3.x does all the magic it self.
Sql:
Create table tblCompany (..., Logo image);
NHibernate-Mapping (important to set length!!!):
<class name="Company"
table="tblCompany">
...
<property name="_logo"
column="Logo"
not-null="false"
length="2147483647"
access="field" />
...
</class>
C#-Class:
public class Company {
...
private Image _logo;
...
}
I'm not sure how to ask the question, for I don't know what I don't know, and therefore I don't know the proper terminology for what I'm trying to get the answer to. I will explain my scenario, in hopes that it will help:
I've got three tables, a Book table, a Tag table and a BookTag lookup table.
Each book has an ID, a Title (for starters)
Each tag has an ID, and a Title
Each BookTag has an ID, a BookID, and a TagID.
A book can be tagged with multiple tags, and a tag can be used on more than one BookID.
I've got my objects setup in this fashion:
Book.cs
int BookID
string Title
List<BookTag> Tags
Tag.cs
int TagID
string Title
BookTag.cs
int ID
int BookID
int TagID
I would like the Books.cs class to have a collection of Tags, and not BookTags, but I cannot seem to get the mapping right in NHibernate. This is what I've got for the Book.hbm.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel.Books">
<class name="DomainModel.Books.Book" table="Books">
<id name="BookID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property name="Title" type="String" not-null="true"/>
<set lazy="true" name="Tags" table="BookTags" generic="true" inverse="true" cascade="delete">
<key column="BookID"/>
<one-to-many class="DomainModel.Books.BookTag, DomainModel"/>
</set>
</class>
</hibernate-mapping>
And this is my BookTag.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel.Books">
<class name="DomainModel.Books.BookTag" table="BookTags">
<id column="BookTagID" name="BookTagID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<many-to-one name="Tag">
<column not-null="true" name="TagID"/>
</many-to-one>
<many-to-one name="Book">
<column not-null="true" name="BookID"/>
</many-to-one>
</class>
</hibernate-mapping>
Under this model, I can get to the tag I want by using my object model: Book.Tags[0].Tag, but that just seems inefficient. Can I use NHibernate to map out the BookTags.TagID with the Tags.TagID in the database so that I can get Book.Tags[0] to return a Tag object, instead of a BookTags object? I didn't know of a better way to associate Books to tags so that a tag used on Book1 can be used on Book2 without adding a new entry to the Tags table.
I hope this makes at least some sense. Let me know if you need further clarification. I'll post my solution here if I figure it out before someone answers.
You don't need a BookTag class at all. You can map Book.Tags collection as many-to-many. To do this you will specify BookTag in the map to connect the association. Look here in section 6.8 Bidirectional Associations.
Thank you Tim, that was what I needed. For those that are curious, I "un-mapped" the BookTag table/objects, and now just have a Book object and a Tag object that are used and mapped to NHibernate.
My Book.hbm.xml was updated to this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel.Books">
<class name="DomainModel.Books.Book" table="Books">
<id name="BookID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property name="Title" type="String" not-null="true"/>
<bag name="Tags" table="BookTag" generic="true">
<key column="BookID" on-delete="noaction"></key>
<many-to-many class="Tag" column="TagID"></many-to-many>
</bag>
</class>
</hibernate-mapping>
I need to create a new Many-To-One relationship on my User entity which joins against another entity. The problem is the other entity has a compound key of which 1 field is a field in the User entity and the other is a field in another Many-To-One entity.
User.Key -> User.NewThing.Key
User.SubThing.Key -> User.NewThing.Key
Below is the invalid mapping file I am ideally wanting to use where JeanieUserTyped is my newthing and the ApplicationId is the key in question which comes from ShortCode.ApplicationId.
Question is how do I tell it to map the application part of the compound key?
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
<class name="JeanieUser" table="DBSVR1.Jeanie_Master.dbo.JeanieUser" select-before-update="false" optimistic-lock="none">
<id name="Id" column="UserId" type="Int32">
<generator class="identity"/>
</id>
<property name="Mobile" type="String"/>
<property name="UniqueReoccurBillingRefId" type="String"/>
<property name="DateJoined" type="DateTime"/>
<property name="IsActive" type="Boolean"/>
<many-to-one name="MobileNetwork" class="MobileNetwork" column="MobileNetworkId" />
<many-to-one name="ShortCode" class="ShortCode" column="ShortCodeId" />
<many-to-one name="MobileHandset" class="MobileHandset" column="HandsetId" />
<many-to-one name="JeanieUserTyped" class="JeanieUserTyped">
<column name="Mobile" />
<column name="ApplicationId" />
</many-to-one>
</class>
</hibernate-mapping>
Can you give more details, sounds like you have 3 entities,
User
SubThing
NewThing
Where NewThing resolves a Many-to-Many with User and SubThing - am I close?
Maybe like this:
User -< SubThing
| |
/\ /\
NewThing
I don't suppose the composite key stuff in nhibernate is relevant?
I couldn't figure out why NHibernate is doing this.
Here's part of my table in MS SQL
CREATE TABLE Person (
nameFamily text,
nameGiven text
)
Here's Person.hbm.xml
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Infosci.Dpd.Model.Person,Infosci.Dpd.Model" table="Person" lazy="true">
<property type="string" name="NameGiven" column="nameGiven" />
<property type="string" name="NameFamily" column="nameFamily" />
</class>
</hibernate>
And in my Person.cs I name my property like the following
string NameFamily
{
get ;
set ;
}
string NameGiven
{
get ;
set ;
}
Then I try to create a record using the following code
ISession session = NHibernateHelper.GetCurrentSession();
Person person = new Person();
person.NameFamily = "lee";
session.Save(person);
And what's weird is when I try do execute it, NHibernate actually change the column name by doing the following
NHibernate: INSERT INTO Person (name_family,name_given.......
So here NHibernate chagne my column name from NameFamily to name_family although I did specify the column name.
Is this a NHibernate bug? Or is there any configuration I need to do?
And here's my hibernate config file
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">Data Source=xxxxxxx;Initial Catalog=xx;Integrated Security=True;Pooling=False;User ID=xxxx;Password=xxxx</property>
<property name="show_sql">true</property>
</session-factory>
</hibernate-configuration>
And this is how I create the sessionFactory
sessionFactory = new `Configuration().Configure("hibernate.cfg.xml").
SetNamingStrategy(ImprovedNamingStrategy.Instance).
AddFile("Person.hbm.xml").
BuildSessionFactory();`
That's a "feature" of SetNamingStrategy(ImprovedNamingStrategy.Instance)
It will add underscores before each uppercase letter in mixed-cased names.
Not sure how you disable it (me not being a nhibernate user)
What I end up doing is just use the default naming strategy or SetNamingStrategy(DefaultNamingStrategy.Instance)
the default naming strategy will leave mix-cased name untouched