NHibernate: Where clause on one-to-many relationships doesn't work when column name is ambiguous - nhibernate

It is possible to specify an arbitrary SQL where clause for collection mappings. For example:
<map name="myEntity" where="foo = 1" />
However if the column name is ambiguous for some reason, the sql fails. For example, this can occur if you are trying to use joins for example.
Given that the table aliases are automatically generated, you can't qualify the column name. This makes the feature seem rather silly. Does anyone know if there is a work around?

NHibernate should figure out the correct alias for the property you are referencing. Is foo a mapped property of the item entity type (the item type that is in the map collection) ?
For example this works:
<class name="Category" table="Category">
<id name="Id">
<generator class="guid.comb" />
</id>
<property name="Name" not-null="true" length="255" />
<bag name="ProductList" table="Product" cascade="none" where="Name like '%test%'" fetch="join">
<key column="CategoryId" />
<one-to-many class="Product" />
</bag>
</class>
There is a property on both Category and the Product class named "Name" but nhibernate will in this case use the on defined on the Product class.

Related

NHibernate filter on property from many-to-one

I'm trying to use an NHibernate filter to filter on a parent class's property, but I keep getting an error that the multi-part identifier "Parent.Active" could not be bound. My filter-def is:
<filter-def name="useActive" />
My parent class has this in the mapping:
<property name="Active">
<column name="ACTIVE" not-null="true" />
</property>
<bag name="Children" table="CHILDREN" inverse="true">
<key>
<column name="PARENT_ID_IN_CHILD" />
</key>
<one-to-many class="ChildType" />
</bag>
My child class has this in the mapping:
<many-to-one name="Parent" class="ParentTyle">
<column name="PARENT_ID_IN_CHILD" />
</many-to-one>
<filter name="useActive" condition="Parent.Active = 1" />
How can I get NHibernate to check the parent column when filtering?
edit: I'm enabling the filter using mySession.EnableFilter("useActive");. I'm also using LINQ-to-NHibernate, but I don't think that should matter.
The error you're receiving came from SQL Server that can't find the column "Active" on the table "Parent".
Keep in mind that when you're defining a filter the string that you put in the condition will simply be appended in the where condition of the select as is. If you want to filter for that field you must first identify the alias nHibernate use for your SQL query than put that alias instead of "Parent". it coube something like "mytable_0" or something like that.

One-to-Many List Not Being Saved with NHibernate

I'm very new to NHibernate, and I'm running into a problem while saving a list of child objects.
NOTE
<class name="Note" table="NOTE">
<id name="NoteID" column="NOTE_ID">
<generator class="identity" />
</id>
...
<list name="Sections" table="NOTE_SECTIONS" cascade="all" lazy="false">
<key column="NOTE_ID"/>
<index column="SORT_ORDER"/>
<one-to-many class="Section"/>
</list>
</class>
NOTE SECTION
<class name="Section" table="NOTE_SECTIONS">
<id name="SectionID" column="Section_ID">
<generator class="identity" />
</id>
<property name="NoteID" column="NOTE_ID"/>
...
</class>
The mappings work perfectly for reading the data. However, when I make a change to the Note Section, The queries it generates appears to be going through the proper steps, but then I get the following error:
NHibernate.Exceptions.GenericADOException: could not delete collection: [Domain.Note.Sections#1][SQL: UPDATE NOTE_SECTIONS SET NOTE_ID = null, SORT_ORDER = null WHERE NOTE_ID = #p0] ---> System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'NOTE_ID', table 'NOTE_SECTIONS'; column does not allow nulls. UPDATE fails.
I have read that in order to save like this it will need to be bidirectional. But I've also read that bidrectional mappings don't work with Lists. It's important that my collection have a maintained order - what's the best way to save?
You should use inverse="true" on your collection mapping if you wish to save child objects in this manner.
<list name="Sections" table="NOTE_SECTIONS" inverse="true" cascade="all" lazy="false">
<key column="NOTE_ID"/>
<index column="SORT_ORDER"/>
<one-to-many class="Section"/>
</list>
Inverse Attribute in NHibernate
probably you would need to refer Note from Note Section as many-to-one relation.

NHibernate Mapping a sublass property to another object via foreign key

I am working on an existing data structure that is not perfect and I have an inheritance mapping issue to solve.
I am using a table per hierarchy and have subclasses with discriminators set up. However the subclassed properties are foreign keys back to other tables. How do I set up my subclass mapping so that when I query the fk property I get an object rather than null? Is this even possible?
My current Mapping
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MVC3" namespace="MVC3.Models">
<class name="Image" table="Images">
<id name="Id" column="ImageId">
<generator class="identity" />
</id>
<discriminator column="ImageType" />
<property name="Url" column="Url" not-null="true" />
<property name="Caption" column="Caption" />
<subclass name="AupairImage" discriminator-value="AupairImage">
<join table="Aupairs" inverse="true">
<key column="AupairId" />
<many-to-one name="Aupair" column="AupairId" class="Aupair" />
</join>
</subclass>
<subclass name="FamilyImage" discriminator-value="FamilyImage">
<join table="Families" inverse="true">
<key column="FamilyId" />
<many-to-one name="Family" column="FamilyId" class="Family" />
</join>
</subclass>
I would have like to add an entity diagram but I cannot post images yet :0(
But the foreign keys AupairId and FamilyId link off back to two other tables and are of the type int 32
I know it would be better to restructure the Aupair And Family entities to have a hierarchy to get rid of the one in images but this would be a last resort due to existing code.
Thanks in advance any help appreciated from you mapping experts....
Realised what I was doing wrong after taking a second look, should have just used a Many-To-One under the Subclass with a defined column
<subclass name="MVC3.Models.FamilyImage, MVC3" discriminator-value="FamilyImage">
<many-to-one cascade="all" class="MVC3.Models.Family, MVC3" name="Family">
<column name="FamilyId" />
</many-to-one>
</subclass>

NHibernate inheritance question

Currently I have the following classes:
class Article with properties id, title and body
class Question : Article with an extra PostedBy property
Then I have a table called Article with the above properties and a table called questions with an ID a foreign key articleID and a PostedBy. Both are in different schemas
I would like to know how are my mappings going to look to represent this relation. Both classes are in different assemblies and i would be very reluctant to put Question logic in Article class/mapping and its assembly.
NHibernate supports three basic inheritance strategies.
table per class hierarchy
table per subclass
table per concrete class
It sounds like you are looking for the table per subclass strategy as you have a table for your Article class and another table for the extra properties on the Question subclass. The mapping might looks something like this:
<class name="Article" table="Article">
<id name="Id" type="Int64" column="ArticleId">
<generator class="native"/>
</id>
<property name="Title" column="Title"/>
<property name="Body" column="Body"/>
...
<joined-subclass name="Question" table="Question">
<key column="ArticleId"/>
<property name="PostedBy" column="PostedBy"/>
...
</joined-subclass>
</class>
However, this doesn't meet your desire to keep the mappings entirely separate. You could have entirely separate mappings, but this might have some side effects as allowing Question to be loaded as a plain Article instead of a Question. With separate mapping the Article class would be straight-forward as expected. The Question class would include a join to access the properties stored in the Article table.
<class name="Article" table="Article">
<id name="Id" type="Int64" column="ArticleId">
<generator class="native"/>
</id>
<property name="Title" column="Title"/>
<property name="Body" column="Body"/>
...
</class>
<class name="Question" table="Question">
<id name="Id" type="Int64" column="QuestionId">
<generator class="native"/>
</id>
<property name="PostedBy" column="PostedBy"/>
...
<join table="Article">
<key column="ArticleId"/>
<property name="Title" column="Title"/>
<property name="Body" column="Body"/>
</join>
</class>

In nHibernate, can I map an abstract base class to a collection?

I have a base class for content items in a CMS I'm building. It's currently marked abstract because I only want derived classes to be instantiated. Derived classes like BlogPost, Article, Photo, etc. are set up as a joined subclass to my ContentBase class in nHibernate.
I'm trying to set up a many-to-many mapping between this class and a Tag class. I want to have a collection of Tags on the ContentBase class, and a collection of ContentBase items on the tag class.
Will nHibernate allow me to map the abstract ContentBase class as a collection on the Tag class? I'm assuming not since it wouldn't be able to instantiate any instances of this class when reconstituting a Tag entity from the db. I really don't want to have to have to use a collection of content items per type (e.g. TaggedBlogPosts, TaggedArticles, etc.) on the Tag class.
The whole reason I'm doing this is because logically, a content item can have many tags, and 1 tag can belong to multiple content items. in order for nHibernate to manage the relationships for me in a mapping table, I believe I have to set up a many-to-many association and add the Tag to the ContentBase.Tags collection and then the content item to the Tags.TaggedContentItems collection before the mapping table entry is created in nHibernate.
Here are my mappings for reference:
<class name="CMS.Core.Model.Tag,CMS.Core" table="bp_Tags">
<id column="TagName" name="TagName" type="String" unsaved-value="">
<generator class="assigned" />
</id>
<bag name="_taggedContentList" table="bp_Tags_Mappings" inverse="true" cascade="save-update" lazy="true">
<key column="TagName" />
<many-to-many class="CMS.Core.Model.ContentBase,CMS.Core" column="Target_Id" />
</bag>
</class>
<class name="CMS.Core.Model.ContentBase,CMS.Core" table="bp_Content">
<id name="Id" column="Id" type="Int32" unsaved-value="0">
<generator class="native"></generator>
</id>
<property name="SubmittedBy" column="SubmittedBy" type="string" length="256" not-null="true" />
<property name="SubmittedDate" column="SubmittedDate" type="datetime" not-null="true" />
<property name="PublishDate" column="PublishDate" type="datetime" not-null="true" />
<property name="State" column="State" type="CMS.Core.Model.ContentStates,CMS.Core" not-null="true" />
<property name="ContentType" column="ContentType" type="CMS.Core.Model.ContentTypes,CMS.Core" not-null="true" />
<bag name="_tagsList" table="bp_Tags_Mappings" lazy="false" cascade="save-update">
<key column="Target_Id" />
<many-to-many class="CMS.Core.Model.Tag,CMS.Core" column="TagName" lazy="false" />
</bag>
...
<joined-subclass name="CMS.Core.Model.BlogPost,CMS.Core" table="bp_Content_BlogPosts" >
<key column="Id" />
<property name="Body" type="string" column="Body" />
<property name="Title" type="string" column="Title" />
</joined-subclass>
...
I would also assume that Hibernate would need to instantiate the base class, which makes sense, as there is data directly linked to it in the DB.
It looks like your data entities are in a separate assembly from your main application. The point of not instantiating the base is from a business point of view, so if you make the constructor internal to the Core assembly, does that accomplish what you want? If not, it may be helpful to ask yourself: who am I protecting this functionality from?
NHibernate should allow you to map the abstract class as a collection as long as you map the abstract class itself (it looks like you have).
An alternative is to change your strategy to the Table-per-class-hierachy approach. This puts all your content into a single table with a discriminator column to define the type of content. NHibernate knows how to materialize each content type based on the discriminator. The downside is that:
Each unique property of the concrete classes has to be of type nullable.
This table can get unwieldy if there are a lot of properties specific to each concrete class.
The table-per-class-hierachy is the preferred default mapping strategy (per NHibernate in Action). I would start with the approach and modify it to table-per-subclass when the need is certain.
A whole separate solution would be keep the mapping as is and rely on query to get the content by tag without worrying about the tags keeping a reference to a collection of content.