Modifying how nHibernate saves Saga data in nServiceBus - c#

I'm having an issue where I'm sending a message to nServiceBus with a message data field of variable length. nServiceBus is using nHibernate to create a table called
[NServiceBus].[PendingMentorEmailSagaData]
from a class called PendingMentorEmailSagaData . The message field is however getting set to nvarchar(255), I am looking for a way to have it set to nvarchar(MAX).
I've tried using an embedded hbm file, but am getting a "persistent class PendingMentorEmailSagaData not found" error.
This probably means I can't figure out what class to set the file too.
The hbm file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="PendingMentorEmailSagaData">
<id name="Id" />
<property name="OriginalMessageId" />
<property name="Originator" />
<property name="PendingMentorEmailCommandId" />
<property name="JobBoardCode" />
</class>
</hibernate-mapping>
PendingMentorEmailSagaData is the name of the saga's data class.

Create a PendingMentorEmailSagaData.hbm.xml file in the same project that the saga exists on, eg:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:nhibernate-mapping-2.2">
<class name="MY_NAMESPACE.PendingMentorEmailSagaData, MY_ASSEMBLY_NAME" table="PendingMentorEmailSagaData" dynamic-update="true" optimistic-lock="all">
<id name="Id" type="Guid">
<generator class="assigned" />
</id>
<property name="Originator" />
<property name="OriginalMessageId" />
<property name="LargeText" type="StringClob" />
</class>
</hibernate-mapping>
2. Mark that file as an Embedded Resource

Related

nhibernate subclass - zero guid in not used column instead of null

I have an issue with a two subclasses using the same table and same fields. Even though the generated table has this fields as nullable uniqueidentifiers, when I save the one record that does not use the third column, then the created field has a value of "000000000-0000-0000-0000-000000000000" instead of NULL. Other parts of application require this place to be null. Here's the code. What's wrong?
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly=".."
namespace="...">
<class name="TEST" table="..." discriminator-value="not null">
<id name="Id" column="tID">
<generator class="assigned" />
</id>
<discriminator column="iTestTypeID" type="Int32" not-null="true"/>
<property name="TotalScore" column="fTotalScore"/>
<property name="IsTimedOut" column="bTimedOut"/>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly=".."
namespace="...">
<subclass name="TestA" extends="TEST" discriminator-value="3">
<many-to-one name="Department" column="uTestCriteria01" cascade="save-update" not-null="false" />
<many-to-one name="Building" column="uTestCriteria02" cascade="save-update" not-null="false" />
</subclass>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly=".."
namespace="...">
<subclass name="TestB" extends="TEST" discriminator-value="3">
<many-to-one name="Building" column="uTestCriteria01" cascade="save-update" not-null="false" />
<many-to-one name="Floor" column="uTestCriteria02" cascade="save-update" not-null="false" />
<many-to-one name="Room" column="uTestCriteria03" cascade="save-update" not-null="false" />
</subclass>
</hibernate-mapping>
My guess would be that your objects aren't using nullable types.
Do you have the types defined like this:
public class A
{
public Guid? field { get; set; }
}
Take a look at this StackOverflow article for an explanation:
How can I default a parameter to Guid.Empty in C#?
Also in your question I would list the specific field(s) you are talking about so there is no confusion and post the code for your objects that are tied to this mapping.

NHibernate - getting one-to-many

Wondering if anyone could point me in the right direction..
I currently have the following 3 tables in my sqlserver database
Parameter
ParameterId
ParameterName
ParameterValue
ParameterValueId
ParameterValue
ParameterParameterValue
ParameterId
ParameterValueId
I'm trying to get it where the Parameter domain object will also fetch all the ParameterValue objects as well (I'm guessing Parameter has a one-to-many relationship with ParameterValue, since a parameter can have more than one value) but I'm getting no where - the msot I've achieved is fetching the first value, rather than all :(
If anyone is willing to help or anything I can post some code and/or the mappings I'm using - as always, any help is much appreciated :)
Mappings for Parameter
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="StockMarketAdvisorDatabaseAccess.Domain"
assembly="StockMarketAdvisorDatabaseAccess">
<class name="Parameter" table="Parameter">
<id name="ParameterId">
<column name="ParameterId" sql-type="int" not-null="true" />
<generator class="identity" />
</id>
<property name="ParameterName" />
<bag name="ParameterValues" table="ParameterParameterValue" cascade="none">
<key column="ParameterValueId" />
<one-to-many class="ParameterValue" />
</bag>
</class>
</hibernate-mapping>
Mappings for ParameterValue
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="StockMarketAdvisorDatabaseAccess.Domain"
assembly="StockMarketAdvisorDatabaseAccess">
<class name="ParameterValue" table="ParameterValue">
<id name="ParameterValueId">
<column name="ParameterValueId" sql-type="int" not-null="true" />
<generator class="identity" />
</id>
<property name="Value" column="ParameterValue"/>
</class>
</hibernate-mapping>
Thanks again, just started using nHibernate so still trying to figure most it out! :)
Your issue is you are describing one thing (1-many) but your table structure is another (many-many)
If you need many values per parameter then you should simplify your table structure to:
Parameter
-------------
* ParameterId
ParameterName
ParameterValue
--------------------
* ParameterValueId
ParameterId
ParameterValue
Then your mapping can use a 1-many mapping:
<class name="Parameter" table="Parameter">
<id name="ParameterId">
<column name="ParameterId" sql-type="int" not-null="true" />
<generator class="identity" />
</id>
<property name="ParameterName" />
<bag name="ParameterValues" table="ParameterValue" cascade="none">
<key column="ParameterId" />
<one-to-many class="ParameterValue" />
</bag>
</class>

Need access to table with string based primary key in nHibernate

I am trying to map a SQL Server database with nHibernate that is full of tables with varchar primary keys that are generated by external software and I need update/read (no insert) access.
I cannot find a way to get past the following error:
XXXX.Tests.GMCRepository_Fixture.Can_get_existing_GMC_by_parameter'
failed: NHibernate.MappingException :
XXXX.Domain.Mappings.GMC2.hbm.xml(4,6): XML validation error: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'property' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id' in namespace 'urn:nhibernate- mapping-2.2'.
Research has suggested this error is relating to there not being a valid primary key (id) defined.
Mapping XML looks like:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="XXXX.Domain" namespace="XXXX.Domain" xmlns="urn:nhibernate-mapping-2.2" schema="GM.dbo">
<class name="GMC2" table="C2" lazy="true" >
<property name="PARAMETER">
<column name="PARAMETER" sql-type="varchar" not-null="true" />
</property>
...
<id name="Recid">
<column name="recid" sql-type="varchar" not-null="true" />
</id>
</class>
</hibernate-mapping>
Thanks for your help!
I believe that the convention is to have the ID mapping as the first thing under the class declaration.
Also as part of the Id mapping you need to specify the Generator of the ID. In your case I think you will need the assigned generator added to your ID mapping. Your class mapping will look something like this.
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="XXXXCRMAPI.Domain" namespace="XXXXCRMAPI.Domain" xmlns="urn:nhibernate-mapping-2.2" schema="GoldMine.dbo">
<class name="GMContact2" table="CONTACT2" lazy="true" >
<id name="Recid">
<generator type="assigned" />
<column name="recid" sql-type="varchar" not-null="true" />
</id>
<property name="Accountno">
<column name="ACCOUNTNO" sql-type="varchar" not-null="true" />
</property>
...
</class>
</hibernate-mapping>

Could not compile the mapping document, Could not instantiate dialect class Nhibernate.Dialect.MsSql2008Dialect

I am using Visual Studio 2010 with NHibernate 3.2.0.GA, I do have a web application with the following Web.Config File:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
</configSections>
<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=.\SQLEXPRESS;AttachDbFilename=C:\Users\Mahshid\Desktop\BugTracker\BugTracker\App_Data\BugTrackerDB.mdf;
Integrated Security=True;User Instance=True
</property>
<property name ="adonet.batch_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">Nhibernate.Dialect.MsSql2008Dialect</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,
NHiberante.ByteCode.LinFu</property>
</session-factory>
</hibernate-configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
</configuration>
I added my sql database as a local one inside vs2010, I also do have two nhibernate hbm.xml files with as follows:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="BugTracker.Model"
assembly ="BugTracker">
<class name="Bug" table ="Bugs" lazy="false">
<id name ="BugId" column ="BugId" type="int"
unsaved-value="0">
<generator class="native"/>
</id>
<property name="Desc" column="Description"/>
<property name="Fixed" column ="Fixed"/>
<many-to-one name="Application"
class="Application"
column="ApplicationId"
cascade="all"
not-null="true"/>
</class>
</hibernate-mapping>
And:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="BugTracker.Model"
assembly="BugTracker">
<class name="Application" table="Applications" lazy="false">
<id name="ApplicationId" column ="ApplicationId" type="int" unsaved-value ="0">
<generator class ="native"></generator>
</id>
<property name ="Name" column="Name"/>
<component access ="field.camelcase-underscore" name ="Developer"
class="Developer">
<property access ="field.camelcase-underscore"
column ="DeveloperFirstName" name="FirstName"/>
<property access ="field.camelcase-underscore"
column="DeveloperLastName" name="LastName"/>
</component>
<bag cascade="all-delete-orphan"
inverse ="true"
name ="Bugs"
lazy="false"
access ="field.camelcase-underscore">
<key column ="ApplicationId"/>
<one-to-many class ="Bug"/>
</bag>
</class>
</hibernate-mapping>
I set them as embedded resource, believe me but I get the exception in the following code part:
private static void Init()
{
NHibernate.Cfg.Configuration config;
config = new NHibernate.Cfg.Configuration();
config.AddAssembly("BugTracker");
config.Configure();
_SessionFactory = config.BuildSessionFactory();
}
With this message:
Could not compile the mapping document: BugTracker.Model.Bug.hbm.xml
Inner Exception Message:
Could not instantiate dialect class Nhibernate.Dialect.MsSql2008Dialect
I know that this is beginer's issue but i am just a newbie! but i appreciate your ideas...
Shouldn't the name of dialect be NHibernate.Dialect.MsSql2008Dialect? I mean H must be capital?

NHibernate Criteria: Add a constraint for property type

I have a program with a base class (Message) from which many other classes derivate (notably Article and Comment). I would like to create a criteria that will select all the Comments for which the RootMessage property is of type Article (I have some other type of potential RootMessages). But I can't seem to find how to add that kind of constraint in a criteria.
For now my code is this:
public virtual ICollection<Comment> GetCommentsByArticle(ISession session)
{
var c = session.CreateCriteria(typeof(Comment))
.Add(Expression.Eq("Author", this))
.AddOrder(Order.Desc("CreationDate"))
.SetMaxResults(20);
var commentList = c.List<Comment>();
return commentList;
}
But of course this returns every single comment of this Author. What I want is every single comment of this Author that have a RootMessage of the Article type.
These are the mappings.
Message:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="FolkeLib"
namespace="Folke.Code.Domain">
<class name="Message" discriminator-value="0">
<id name="Id">
<generator class="native"></generator>
</id>
<discriminator column="MessageType" type="Int32"/>
<timestamp column="ModificationDate" name="ModificationDate"/>
<property name="CreationDate" index="ArticleCreationDate"/>
<many-to-one name="Author"/>
<property name="Text" type="StringClob">
<column name="Text" sql-type="text"/>
</property>
<property name="Locked"/>
<many-to-one name="Locker" not-null="false"/>
<many-to-one name="RootMessage" not-null="false"/>
<many-to-one name="ParentMessage" not-null="false"/>
<property name="Score"/>
<many-to-one name="Site" not-null="true"/>
Article:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="FolkeLib"
namespace="Folke.Code.Domain">
<subclass name="Article" extends="Message" discriminator-value="1">
<property name="Title"/>
<set name="TagSet" lazy="true" table="MessageTag">
<key column="MessageId"/>
<many-to-many class="Tag" column="TagId"/>
</set>
<set name="ImageSet" lazy="true" table="MessageImage">
<key column="MessageId"/>
<many-to-many class="Image" column="ImageId"/>
</set>
<many-to-one name="Forum"/>
</subclass>
</hibernate-mapping>
Comment (class is pretty much empty for now):
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="FolkeLib"
namespace="Folke.Code.Domain">
<subclass name="Comment" extends="Message" discriminator-value="2">
</subclass>
</hibernate-mapping>
Any help appreciated!
This would be easier to answer if you posted your complete mappings, but I believe something along the lines of:
.CreateAlias("RootMessage", "rm")
.Add(Expression.Eq("rm.class",typeof(Article)))
Is what you're looking for.

Categories