The given key was not present in the dictionary NHibernate on Delete - nhibernate-mapping

I am having problems deleting an entity from the database using NHibernate v3.
foreach (ShoppingCart s in query )
{
_session.Delete(s);
trans.Commit();
break;
}
"The given key was not present in the dictionary"
There really isn't any more specific information than that. Basically, I'm using two entities as shown below:
| ShoppingCart |==========> | Product |
ShoppingCart PK: ShoppingCartID, ProductID (also is FK)
Product PK: ProductID (no FK)
... A ShoppingCart entity which has many Products inside it.
My ShoppingCart mapping entity look like this:
<class name="ShoppingCart" table="LC_SHOPPINGCART" lazy="true" >
<composite-id>
<key-property name="CartID" column="CARTID" />
<key-property name="ProductID" column="PRODUCTID" />
<key-property name="Size" column="SIZE" />
<key-property name="Color" column="COLOR" />
</composite-id>
<many-to-one foreign-key="ProductID" insert="false" update="false" lazy="false" name="Product">
<column name="PRODUCTID" sql-type="INT" not-null="true" />
</many-to-one>
<property name="Quantity">
<column name="QUANTITY" sql-type="INT" not-null="false" />
</property>
<property name="DateAdded">
<column name="DATEADDED" sql-type="SMALLDATETIME" not-null="false" />
</property>
<property name="Price">
<column name="PRICE" sql-type="MONEY" not-null="false" />
</property>
And the Entity class for ShoppingCart:
public ShoppingCart() { }
[Key]
public virtual string CartID { get; set; }
public virtual int ProductID { get; set; }
public virtual string Size { get; set; }
public virtual string Color { get; set; }
public virtual Product Product { get; set; }
public virtual System.Nullable<int> Quantity { get; set; }
public virtual DateTime DateAdded { get; set; }
public virtual System.Nullable<decimal> Price { get; set; }
My Product Mapping looks like this:
<class name="Product" table="LC_PRODUCT" lazy="true" >
<id name="ProductID" column="ProductID">
<generator class="native"></generator>
</id>
<list name="ShoppingCarts"
cascade="all-delete-orphan">
<key column="ProductID"></key>
<index column="CartID"></index>
<one-to-many class="ShoppingCart"></one-to-many>
</list>
<property name="Name">
<column name="NAME" sql-type="NVARCHAR" not-null="false" />
</property>
<property name="Description">
<column name="DESCRIPTION" sql-type="VARCHAR" not-null="false" />
</property>
<property name="Price">
<column name="PRICE" sql-type="MONEY" not-null="false" />
</property>
<property name="Image1FileName">
<column name="IMAGE1FILENAME" sql-type="NVARCHAR" not-null="false" />
</property>
<property name="Image2FileName">
<column name="IMAGE2FILENAME" sql-type="NVARCHAR" not-null="false" />
</property>
<property name="OnCatalogPromotion">
<column name="ONCATALOGPROMOTION" sql-type="BIT" not-null="false" />
</property>
<property name="OnDepartmentPromotion">
<column name="ONDEPARTMENTPROMOTION" sql-type="BIT" not-null="false" />
</property>
<property name="Sizeable">
<column name="SIZEABLE" sql-type="BIT" not-null="false" />
</property>
<property name="Colorable">
<column name="COLORABLE" sql-type="BIT" not-null="false" />
</property>
<property name="DateAdded">
<column name="DATEADDED" sql-type="SMALLDATETIME" not-null="false" />
</property>
<property name="TotalRemaining">
<column name="TOTALREMAINING" sql-type="INT" not-null="false" />
</property>
</class>
...And the corresponding Product entity class:
public Product() { }
[Key]
public virtual int ProductID { get; set; }
public virtual IList<ShoppingCart> ShoppingCarts { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual System.Nullable<decimal> Price { get; set; }
public virtual string Image1FileName { get; set; }
public virtual string Image2FileName { get; set; }
public virtual bool OnCatalogPromotion { get; set; }
public virtual bool OnDepartmentPromotion { get; set; }
public virtual bool Sizeable { get; set; }
public virtual bool Colorable { get; set; }
public virtual DateTime DateAdded { get; set; }
public virtual System.Nullable<int> TotalRemaining { get; set; }
The stack trace is provided as follows:
Server Error in '/ElectronicsRob' Application.
The given key was not present in the dictionary.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
Source Error:
Line 106: //db.lc_ShoppingCarts.DeleteOnSubmit(query);
Line 107: //db.SubmitChanges();
Line 108: new ShoppingCartRepository().DeleteProductFromCart( System.Convert.ToInt32 (Grid1.SelectedDataKey["ProductID"]), LinqShoppingCartAccess.cartID);
Line 109: PopulateControls();
Line 110: }
Source File: c:\inetpub\wwwroot\ElectronicsRob\LINQControls\ControlTemplates\LinqShoppingCart.ascx.cs
Line: 108
Stack Trace:
[KeyNotFoundException: The given key was not present in the dictionary.]
NHibernate.Engine.StatefulPersistenceContext.RemoveEntity(EntityKey key) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\StatefulPersistenceContext.cs:435
NHibernate.Action.EntityDeleteAction.Execute() in d:\CSharp\NH\nhibernate\src\NHibernate\Action\EntityDeleteAction.cs:88
NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:136
NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:125
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:241
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs:20
NHibernate.Impl.SessionImpl.Flush() in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:1477
NHibernate.Transaction.AdoTransaction.Commit() in d:\CSharp\NH\nhibernate\src\NHibernate\Transaction\AdoTransaction.cs:190
ObjexxRepositories.ShoppingCartRepository.DeleteProductFromCart(Nullable`1 prodID, String cartID) in C:\Users\Rob\Documents\Visual Studio 2010\Projects\NGC6744\ObjexxRepositories\Concrete\ShoppingCartRepository.cs:78
LINQControls_LinqShoppingCart.Grid1_RowDeleting(Object sender, GridViewDeleteEventArgs e) in c:\inetpub\wwwroot\ElectronicsRob\LINQControls\ControlTemplates\LinqShoppingCart.ascx.cs:108
System.Web.UI.WebControls.GridView.HandleDelete(GridViewRow row, Int32 rowIndex) +814
System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +431
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3707
Any help is appreciated, thank you!

Related

Cannot understand lazy loading properly in ORM technology

I am new to NHibernate. I have created two tables in sql server like UserDetails and its corresponding Products table. The mapping are like!
My entity classes
public class UserDetails
{
[Required(ErrorMessage = "Please enter User Id")]
public virtual string UserId { get; set; }
[Required(ErrorMessage = "Please enter User Name")]
public virtual string UserName { get; set; }
[Required(ErrorMessage = "Please enter Password")]
public virtual string Password { get; set; }
[Required(ErrorMessage = "Please enter Email Id")]
[EmailAddress(ErrorMessage = "Please enter proper Email Id")]
public virtual string EmailId { get; set; }
[Required(ErrorMessage = "Please enter Address")]
[DataType(DataType.MultilineText)]
public virtual string Address { get; set; }
[Required(ErrorMessage = "Please enter Phone No")]
public virtual string PhoneNo { get; set; }
public virtual ISet<Product> Products { get; set; }
}
public class Product
{
[HiddenInput(DisplayValue=false)]
public virtual int ProductID { get; set; }
[Required(ErrorMessage="Please enter a product name")]
public virtual string Name { get; set; }
[DataType(DataType.MultilineText)]
[Required(ErrorMessage = "Please enter a description")]
public virtual string Description { get; set; }
[Required]
[Range(0.01,double.MaxValue,ErrorMessage="Please enter a positive price")]
public virtual decimal Price { get; set; }
[Required(ErrorMessage = "Please specify a category")]
public virtual string Category { get; set; }
public virtual byte[] ImageData { get; set; }
[HiddenInput(DisplayValue=false)]
public virtual string ImageMimeType { get; set; }
public virtual UserDetails UserDetail { get; set; }
}
Mapping
UserDetails.hbm.xml
<class name="SportsStore.Domain.Entities.UserDetails,SportsStore.Domain" table="UserDetails" lazy="true" >
<id name="UserId" column="UserId" access="property" type="String" >
<generator class="assigned"></generator>
</id>
<property name="UserName" column="UserName" access="property" type="String" ></property>
<property name="Password" column="Password" access="property" type="String"></property>
<property name="EmailId" column="EmailId" access="property" type="String" ></property>
<property name="Address" column="Address" access="property" type="String" ></property>
<property name="PhoneNo" column="PhoneNo" access="property" type="String" ></property>
<set name="Products" lazy="true" cascade="all-delete-orphan" inverse="true" >
<key column="UserId" ></key>
<one-to-many class="SportsStore.Domain.Entities.Product"></one-to-many>
</set>
Products.hbm.xml
<class name="SportsStore.Domain.Entities.Product,SportsStore.Domain" table="Products">
<id name="ProductID" column="ProductID" access="property" type="Int32" >
<generator class="native"></generator>
</id>
<property name="Name" column="Name" access="property" type="String">
</property>
<property name="Description" column="Description" access="property" type="String"></property>
<property name="Price" column="Price" access="property" type="decimal"></property>
<property name="Category" column="Category" access="property" type="String"></property>
<property name="ImageData" column="ImageData" access="property" type="BinaryBlob" length="2147483647"></property>
<property name ="ImageMimeType" column="ImageMimeType" access="property" type="String" ></property>
<many-to-one name="UserDetail" column="UserId" class="SportsStore.Domain.Entities.UserDetails" access="property" cascade="all"></many-to-one>
var user = (from userDetails in _session.Query<UserDetails>()
where userDetails.UserId == userId && userDetails.Password == password
select userDetails);
I thought I will get data from only userdetails as lazy loading is applied to it, but on debug mode I can see data from products table too. why? am I understood lazy loading in wrong way or is there any bug in my mapping? According to my knowledge lazy loading loads the data only on demand means if we iterate then the data gets loaded from products table.
Your assumption:
...According to my knowledge lazy loading loads the data only on demand means if we iterate then the data gets loaded from products table
Is absolutely correct. There is no but. Only on demand, for example if we want to iterate them. And exactly that is happening in the debug window.
Debug window is application as some other winform, exe, wpf... It simply prvides native/built in UI to observe our objcets. And once we start to observe/iterate them - they realize that there is demand - data from products table is loaded.
How to be sure?
Not so complicated. Just before starting to observe any object in the Debug window, call: session.Clear(). From that moment, only stuff already loaded will be available later.
So, in debug window, we should now see some exception about lazy loading failure...

Multiple update statements issued before an the insert statement in NHibernate on a many to many relationship

I've spent a couple of days researching this on Google, StackOverflow and reading various blogs on this but to no avail. My question is if a collection is updated within an entity then would this cause NHibernate to update all properties in the entity of the modified collections? In this case I've added a user to a role and once I call session.SaveOrUpdate then 2 updates occur (NHibernate updates user and role) then the INSERT occurs. Is this the default behavior? I've tried to do the following to see if I can get NHibernate to just issue the INSERT statement:
Ran a Ghostbuster test on these entities based on code by Jason Dentler and Fabio Maulo but everything comes back ok and there are no dirty properties.
I made properties nullable that are defined as null in the database.
Set Inverse true on one of the entites.
Any help or insight is much appreciated.
Here are the mapping and class files.
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="Custom.NHibernateLib.Model" assembly="Custom.NHibernateLib" xmlns="urn:nhibernate-mapping-2.2">
<class name="Users">
<id name="UserId" type="Int64">
<generator class="hilo" />
</id>
<property name="ApplicationName" type="String" length="50" />
<property name="Username" type="String" length="15" />
<property name="Email" type="String" length="15" />
<property name="Password" type="String" length="50" />
<property name="PasswordSalt" type="String" length="128" />
<property name="PasswordQuestion" type="String" length="15" />
<property name="PasswordAnswer" type="String" length="50" />
<property name="IsApproved" type="YesNo" />
<property name="LastActivityDate" type="DateTime" />
<property name="LastLoginDate" type="DateTime" />
<property name="LastPasswordChangedDate" type="DateTime" />
<property name="CreationDate" type="DateTime" />
<property name="IsOnline" type="YesNo" />
<property name="IsAnonymous" type="YesNo" />
<property name="IsLockedOut" type="YesNo" />
<property name="LastLockedOutDate" type="DateTime" />
<property name="FailedPasswordAttemptCount" type="Int32" />
<property name="FailedPasswordAttemptWindowStart" type="DateTime" />
<property name="FailedPasswordAnswerAttemptCount" type="Int32" />
<property name="FailedPasswordAnswerAttemptWindowStart" type="DateTime" />
<property name="Comment" type="String" length="4001" />
<bag name="RoleList" table="UserRoles" lazy="true" cascade="save-update, persist" batch-size="10">
<key column="UserId" not-null="true" />
<many-to-many class="Roles" foreign-key="FK_Roles_UserRoles_RoleId">
<column name="RoleId" not-null="true" />
</many-to-many>
</bag>
<one-to-one name="Profiles" />
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="Custom.NHibernateLib.Model" assembly="Custom.NHibernateLib" xmlns="urn:nhibernate-mapping-2.2">
<class name="Roles">
<id name="RoleId" type="Int64">
<generator class="hilo" />
</id>
<property name="ApplicationName" type="String" length="50" />
<property name="RoleName" type="String" length="50" />
<bag name="UserList" table="UserRoles" lazy="true" inverse="true" cascade="save-update, persist" batch-size="10">
<key column="RoleId" not-null="true" />
<many-to-many class="Users" foreign-key="FK_User_UserRoles_UserId">
<column name="UserId" not-null="true" />
</many-to-many>
</bag>
</class>
</hibernate-mapping>
Here are the class files:
using System;
using System.Collections.Generic;
namespace Custom.NHibernateLib.Model
{
public class Users : Entity
{
public Users (){}
public virtual long UserId { get; set; }
public virtual string ApplicationName { get; set; }
public virtual string Username { get; set; }
public virtual string Email { get; set; }
public virtual string Password{ get; set; }
public virtual string PasswordSalt { get; set; }
public virtual string PasswordQuestion { get; set; }
public virtual string PasswordAnswer { get; set; }
public virtual bool? IsApproved { get; set; }
public virtual DateTime? LastActivityDate { get; set; }
public virtual DateTime? LastLoginDate { get; set; }
public virtual DateTime? LastPasswordChangedDate { get; set; }
public virtual DateTime? CreationDate { get; set; }
public virtual bool? IsOnline { get; set; }
public virtual bool? IsAnonymous { get; set; }
public virtual bool? IsLockedOut { get; set; }
public virtual DateTime? LastLockedOutDate { get; set; }
public virtual int? FailedPasswordAttemptCount { get; set; }
public virtual DateTime? FailedPasswordAttemptWindowStart { get; set; }
public virtual int? FailedPasswordAnswerAttemptCount { get; set; }
public virtual DateTime? FailedPasswordAnswerAttemptWindowStart { get; set; }
public virtual string Comment { get; set; }
public virtual IList<Roles> RoleList { get; set; }
public virtual Profiles Profiles { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace Custom.NHibernateLib.Model
{
public class Roles : Entity
{
public Roles(){}
public virtual long RoleId { get; set; }
public virtual string ApplicationName { get; set; }
public virtual string RoleName { get; set; }
public virtual IList<Users> UserList { get; set; }
}
}
Adding the user and the role to their respective collections.
usr.RoleList.Add(role);
role.UserList.Add(usr);
When this is called session.SaveOrUpdate(role) then this occurs in NHibernate.
-- statement #1
UPDATE Users...WHERE UserId = 32768
-- statement #2
UPDATE Roles...WHERE RoleId = 65536
-- statement #3
INSERT INTO UserRoles...
Ok well I can conclude the my issue was caused by the way I was handling the session and commit after the save and update. I was closing the session then recreating it within multiple methods in my custom membership library code. For example, each method I was calling I was wrapping it around a using statement for the session and transaction. I should have known better and not go by my assumptions and just spend the time to RTM.
The NHibernate in Action book about session management and using current session context is what guided me. I coded that up to use in my unit test and everything worked fine. Though the book is a bit dated it still had some good basic info.

Mapping legacy database with possibly a discriminator

I am trying to map a legacy database. I need to implement what I believe should be a discriminator. My problem is discriminators only seem to work when there is a column to differentiate or a formula on the current row. For my case there is no actual differentiator, the data is either joined to one table if it exists, if not, then the other table. To make things even more complicated the table uses a composite key.
Here's an example (it might be oversimplified as I am making it up):
Given my code
public class SomeTable {
public virtual int DataID { get; set; }
public virtual int EmployeeOrCustomer { get; set; }
public virtual Person Person { get; set; }
public virtual int SomeValue { get; set; }
}
public abstract class Person {
public virtual int ID { get; set; }
public virtual string Name { get; set; }
}
public class Employee : Person {
public virtual int EmployeeNumber { get; set; }
}
public class Customer : Person {
public virtual int CustomerNumber { get; set; }
}
And my Data
-SomeTable-
DataID(K) EmployeeOrCustomer(K) SomeValue
1 1 100
1 22 222
-Employee-
ID Name EmployeNumber
1 Joe Blow 12345
-Customer-
ID Name CustomerNumber
22 ACME Inc. 4242
My Mappings:
<class name="SomeTable" abstract="true">
<composite-id>
<key-property name="DataID" />
<key-property name="EmployeeOrCustomer" />
</composite-id>
<property name="SomeValue" />
<!-- ?????? -->
</class>
<class name="Employee">
<id name="ID" />
<Property name="EmployeeNumber">
</Class>
<class name="Customer">
<id name="ID" />
<Property name="CustomerNumber">
</Class>
What I expect
DataID: 1, SomeValue: 100 Person: { Employee: EmployeeNumber: 12345 }
DataID: 1, SomeValue: 222, Person: { Customer: CustomerNumber: 4242 }
I thought about joining the 2 tables and using the merged tables as a join but the 2 tables differ a lot. Also, I can't modify the schema so adding a discriminator column is not an option.
Any ideas?
i think what you are searching for is union subclass inheritance mapping
<class name="Person" abstract="true">
<id name="Id">
<generator class="assigned"/>
</id>
<union-subclass table="Employee" name="Employee">
<property name="Name"/>
<property name="EmployeeNumber"/>
</union-subclass>
<union-subclass table="Customer" name="Customer">
<property name="Name"/>
<property name="CustomerNumber"/>
</union-subclass>
</class>
<class name="SomeTable" abstract="true">
<composite-id>
<key-property name="DataID" />
<key-many-to-one name="Person" column="EmployeeOrCustomer" />
</composite-id>
<property name="SomeValue" />
</class>
Note the extra property EmployeeOrCustomer is not needed.

nhibernate weird DuplicateMappingException

I have two classes:
namespace fm.web
{
public class User
{
public static string default_username = "guest";
public static string default_password = "guest";
private UserType usertype;
public virtual int? Id { get; set; }
public virtual string Username { get; set; }
public virtual string Password { get; set; }
public virtual DateTime Datecreated { get; set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
public virtual string Email { get; set; }
public virtual UserType Usertype
{
get { return usertype; }
set { usertype = value; }
}
}
}
namespace fm.web
{
public class UserType
{
public virtual int? Id { get; set; }
public virtual string Title { get; set; }
}
}
Here are the mapping files
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="fm.web"
assembly="fm.web">
<class name="User" table="[user]">
<id name="Id">
<column name="id" />
<generator class="native" />
</id>
<property name="Username" />
<property name="Password" />
<property name="Datecreated" />
<many-to-one name="Usertype"
class="UserType"
column="[type]"
cascade="all"
lazy="false"
/>
<property name="Firstname" />
<property name="Lastname" />
<property name="Email" />
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="fm.web"
assembly="fm.web">
<class name="UserType" table="[user_type]">
<id name="Id">
<column name="id" />
<generator class="native" />
</id>
<property name="Title" />
</class>
</hibernate-mapping>
I'm getting an exception: DuplicateMappingException
Could not compile the mapping document: fm.web.data.User.hbm.xml
Duplicate class/entity mapping User
Is nhibernate always this hard? Maybe I need a different framework.
I really think the mappings are fine which leads me to believe that the configuration setup is not quite right.
Please can you check that BuildSessionFactory is only called once on application start up.
Also please check that you are not including the mapping files twice as this will also throw this type of error.
Please post your configuration code.
You are correct in thinking that NHibernate is difficult to grasp for new comers espically the session management and mappings. Once you have grasped this then things get easier and are well worth the effort.

nhibernate <bag> exception - illegal access to loading collection

I am getting "illegal access to loading collection" exception while trying to populate "IList" property in Supplier Domain using NHibernate . I have tried all suggestions I got by googling but nothing seems to help :(
Here are my domain objects and .HBM files. I would greatly appreciate your help/suggestions.
Supplier Domain Object
namespace Inventory.DomainObjects
{
[Serializable]
public class Supplier
{
public virtual string SupplierID { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual IList<Address> Address { get; set; }
}
}
Address Domain Object
namespace Inventory.DomainObjects
{
[Serializable]
public class Address
{
public virtual int AddressID { get; set; }
public virtual string SupplierID { get; set; }
public virtual string Line1 { get; set; }
public virtual string Line2 { get; set; }
public virtual string Line3 { get; set; }
}
}
Supplier.HBM
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Inventory.DomainObjects"
assembly="Inventory">
<class name="Supplier" table="Inv_Supplier">
<id name="SupplierID" column="SupplierId" type="string"/>
<property name="SupplierCode" column="Code" type="string"/>
<property name="Name" column="SupplierName" type="string"/>
<property name="Description" column="SupplierDescription" type="string"/>
<bag name="Address" cascade="all" inverse="true" lazy="true">
<key column="SupplierID" not-null="true"/>
<one-to-many class="Address" not-found="ignore"/>
</bag>
</class>
</hibernate-mapping>
Address.HBM
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Inventory.DomainObjects"
assembly="Inventory">
<class name="Address" table="Inv_Supplier_Address" lazy="false">
<id name="AddressID" column="AddressId" type="integer"/>
<property name="Line1" column="Line1" type="string"/>
<property name="Line2" column="Line2" type="string"/>
<property name="Line3" column="Line3" type="string"/>
<many-to-one name="SupplierID" column="SupplierId" not-null="true" class="Supplier" />
</class>
</hibernate-mapping>
This looks suspicious:
<many-to-one name="SupplierID" column="SupplierId"
not-null="true" class="Supplier" />
Could you try removing the above line to see if the problem goes away?
If this fixes the problem you should add the many-to-one back as follows:
namespace Inventory.DomainObjects
{
[Serializable]
public class Address
{
public virtual int AddressID { get; set; }
// CHANGED: reference supplier object instead of ID
public virtual Supplier Supplier { get; set; }
public virtual string Line1 { get; set; }
public virtual string Line2 { get; set; }
public virtual string Line3 { get; set; }
}
}
then change your hbm mapping file like this (to reference the Supplier property instead of SupplierId
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Inventory.DomainObjects"
assembly="Inventory">
<class name="Address" table="Inv_Supplier_Address" lazy="false">
<id name="AddressID" column="AddressId" type="integer"/>
<property name="Line1" column="Line1" type="string"/>
<property name="Line2" column="Line2" type="string"/>
<property name="Line3" column="Line3" type="string"/>
<many-to-one name="Supplier" column="SupplierId"
not-null="true" class="Supplier" />
</class>
</hibernate-mapping>