Deserialization fail due to new WCF DataMember - wcf

I have a WCF webservice that my C++ client talks to using a proxy generated by svcutil + wsutil.
I added a new DataMember, and now i get:
Serialization failure occurred when reading an element with WS_READ_OPTION '2', name 'GetMachineRequestDetailsResponse' and namespace 'M.NativeOM'.; Serialization failure occurred when reading a field with WS_TYPE '26 (0x1A)', WS_FIELD_MAPPING '2', name 'GetMachineRequestDetailsResult' and namespace 'M.NativeOM'.; An error occurred at row 1, column 796 (0x31C) when the XML reader is processing the input source.; An end element was expected.; A start element with the name 'UseForRun_SnapshotID' and namespace 'M.NativeOM' was found, but not expected.;
My data members with in a datacontract is defined using Order attribute:
[DataMember(Order = 4)]
public int MachineID { get; set; }
[DataMember(Order = 5)]
public string MachineName { get; set; }
[DataMember(Order = 3)]
public bool IsReserved { get; set; }
[DataMember(Order = 13)]
public string ReservedBy { get; set; }
[DataMember(Order = 12)]
public MdMachineRequestType RequestType { get; set; }
[DataMember(Order = 0)]
public bool CommandIsAdmin { get; set; }
[DataMember(Order = 1)]
public string CommandLine { get; set; }
[DataMember(Order = 2)]
public int CommandTimeout { get; set; }
[DataMember(Order = 7)]
public string MoveToDb_ServerName { get; set; }
[DataMember(Order = 6)]
public string MoveToDb_DatabaseName { get; set; }
[DataMember(Order = 11)]
public int Reimage_OsID { get; set; }
[DataMember(Order = 8)]
public int Reimage_ImageID { get; set; }
[DataMember(Order = 9)]
public int Reimage_OptionTimeout { get; set; }
[DataMember(Order = 10)]
public string Reimage_OptionUserName { get; set; }
[DataMember(Order = 15)]
public int UseForRun_RunID { get; set; }
[DataMember(Order = 14)]
public bool UseForRun_DoCleanInstall { get; set; }
[DataMember(Order = 16)]
public int UseForRun_SnapshotID { get; set; }
Also, the generated xsd file shows them in the right sequence
<xs:complexType name="MdMachineRequest">
<xs:sequence>
<xs:element minOccurs="0" name="CommandIsAdmin" type="xs:boolean" />
<xs:element minOccurs="0" name="CommandLine" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="CommandTimeout" type="xs:int" />
<xs:element minOccurs="0" name="IsReserved" type="xs:boolean" />
<xs:element minOccurs="0" name="MachineID" type="xs:int" />
<xs:element minOccurs="0" name="MachineName" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="MoveToDb_DatabaseName" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="MoveToDb_ServerName" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="Reimage_ImageID" type="xs:int" />
<xs:element minOccurs="0" name="Reimage_OptionTimeout" type="xs:int" />
<xs:element minOccurs="0" name="Reimage_OptionUserName" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="Reimage_OsID" type="xs:int" />
<xs:element minOccurs="0" name="RequestType" type="tns:MdMachineRequestType" />
<xs:element minOccurs="0" name="ReservedBy" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="UseForRun_DoCleanInstall" type="xs:boolean" />
<xs:element minOccurs="0" name="UseForRun_RunID" type="xs:int" />
<xs:element minOccurs="0" name="UseForRun_SnapshotID" type="xs:int" />
</xs:sequence>
</xs:complexType>
So using Order attribute did put DataMembers in the right sequence but my client doesn't just ignore new DataMember and instead give an error.

the problem was that when i create proxy using wsutil, i was missing /ignoreTrailingContent option

Related

"ArrayOf..." simpleWsdl WCF

I am creating WCF to communicate with SAP and have to send arrays of different objects.
Here is an example of DataContracts
[DataContract]
public class MesPet12
{
[DataMember(IsRequired = true, Order = 1)]
public DateTime Date { get; set; }
[DataMember(Name = "Shifts")]
public ShiftMes[] Shifts { get; set; }
}
[DataContract(Name = "Shift")]
public class ShiftMes
{
[DataMember(IsRequired = true, Order = 1)]
public string Id { get; set; }
[DataMember(Order = 2)]
public Order[] Orders { get; set; }
}
In singleWsd there is the following:
<xs:complexType name="MesPet12">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Date" type="xs:dateTime"/>
<xs:element minOccurs="0" maxOccurs="1" name="Shifts" type="tns:ArrayOfShiftMes"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfShiftMes">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="ShiftMes" nillable="true"
type="tns:ShiftMes"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ShiftMes">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Id" type="xs:string"/>
<xs:element minOccurs="0" maxOccurs="1" name="Orders" type="tns:ArrayOfOrder"/>
</xs:sequence>
</xs:complexType>
As you can see the new ComplexType "ArrayOfShiftMes" was generated. Everythings works fine, but as I know SAP doesn't like something like "ArrayOf...".
How can I either avoid creating extra complex type "ArrayOf" or rename it?
If somebody face with the same issue, the solution is the following:
you just need to add the attribute
[System.Xml.Serialization.XmlElementAttribute("Shifts", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ShiftMes[] Shifts { get; set; }

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.

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

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!

Problem with one-to-many mapping using composite keys

I have two tables in a legacy database that I need to map using NHibernate. Unfortunately, one of these tables are using a composite key and I am running into a problem which I describe below.
Firstly, here is the schema of the two tables:
CREATE TABLE [dbo].[tBenchmarkFxHedgeHistory](
[BenchmarkFxHedgeHistoryId] [int] IDENTITY(1,1) NOT NULL,
[BenchmarkFxHedgeId] [int] NOT NULL,
[ModelId] [int] NOT NULL,
[BaseCurrencyCode] [nvarchar](5) NOT NULL,
[BenchmarkFxHedgeTypeId] [int] NOT NULL,
[DateFrom] [smalldatetime] NOT NULL,
[DateTo] [smalldatetime] NULL,
[PctHedgeBackToBase] [decimal](13, 10) NULL,
[Enabled] [bit] NOT NULL,
[BenchmarkHedgeStatusId] [int] NOT NULL,
[AuditActionId] [int] NOT NULL,
[Timestamp] [timestamp] NOT NULL,
[HistoryUser] [nvarchar](50) NOT NULL CONSTRAINT [DF_tBenchmarkFxHedgeHistory_HistoryUser] DEFAULT (suser_sname()),
[HistoryDate] [datetime] NOT NULL CONSTRAINT [DF_tBenchmarkFxHedgeHistory_HistoryDate] DEFAULT (getdate()),
CONSTRAINT [PK_tBenchmarkFxHedgeHistory] PRIMARY KEY CLUSTERED
(
[BenchmarkFxHedgeHistoryId] ASC
)
CREATE TABLE [dbo].[tBenchmarkFxHedgeRatio](
[BenchMarkFxHedgeId] [int] NOT NULL,
[NonBaseCurrencyCode] [nvarchar](5) NOT NULL,
[PctHedgeBackToBase] [decimal](13, 10) NOT NULL,
CONSTRAINT [PK_tBenchmarkFxHedgeRatio] PRIMARY KEY CLUSTERED
(
[BenchMarkFxHedgeId] ASC,
[NonBaseCurrencyCode] ASC
)
And here are the domain classes:
public class BenchmarkFxHedgeRuleHistory
{
private IList<BenchmarkFxRuleRatioHistory> _percentages = new List<BenchmarkFxRuleRatioHistory>();
public virtual int Id { get; set; }
public virtual string BaseCurrencyCode { get; set; }
public virtual DateTime DateFrom { get; set; }
public virtual DateTime? DateTo { get; set; }
public virtual decimal? Percentage { get; set; }
public virtual bool Enabled { get; set; }
public virtual byte[] Timestamp { get; set; }
public virtual BenchmarkFxHedgeStatus Status { get; set; }
public virtual BenchmarkFxHedgeType Strategy { get; set; }
public virtual Model Model { get; set; }
public virtual BenchmarkFxHedgeRule Rule { get; set; }
public virtual AuditAction AuditAction { get; set; }
public virtual IList<BenchmarkFxRuleRatioHistory> Percentages
{
get { return _percentages; }
}
}
[Serializable]
public class BenchmarkFxRuleRatioHistory
{
public virtual string NonBaseCurrencyCode { get; set; }
public virtual decimal Percentage { get; set; }
public virtual BenchmarkFxHedgeRuleHistory HistoryEntry { get; set; }
public override bool Equals(object obj)
{
var rule = obj as BenchmarkFxRuleRatioHistory;
if (rule == null) return false;
return rule.HistoryEntry.Id == HistoryEntry.Id && NonBaseCurrencyCode == rule.NonBaseCurrencyCode;
}
public override int GetHashCode()
{
return NonBaseCurrencyCode.GetHashCode() ^ HistoryEntry.GetHashCode();
}
}
And finally, here are the NHibernate mapping files:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Tests.DomainModel" assembly="Tests.DomainModel" xmlns="urn:nhibernate-mapping-2.2">
<class name="BenchmarkFxHedgeRuleHistory" table="`tBenchmarkFxHedgeHistory`" schema="`dbo`">
<id name="Id" access="property" column="`BenchmarkFxHedgeHistoryId`">
<generator class="native" />
</id>
<many-to-one name="Rule" class="BenchmarkFxHedgeRule" column="`BenchmarkFxHedgeId`" not-null="true" fetch="select" />
<property name="BaseCurrencyCode" type="String" column="`BaseCurrencyCode`" length="5" />
<property name="DateFrom" type="DateTime" column="`DateFrom`" />
<property name="DateTo" type="DateTime" column="`DateTo`" />
<property name="Enabled" type="Boolean" column="`Enabled`" />
<property name="Percentage" type="Decimal" column="`PctHedgeBackToBase`" />
<property name="Timestamp" type="BinaryBlob" column="`Timestamp`" />
<many-to-one name="Status" class="BenchmarkFxHedgeStatus" column="`BenchmarkHedgeStatusId`" not-null="true" fetch="join" />
<many-to-one name="Strategy" class="BenchmarkFxHedgeType" column="`BenchmarkFxHedgeTypeId`" not-null="true" fetch="join" />
<many-to-one name="Model" class="Model" column="`ModelId`" not-null="true" fetch="select" />
<many-to-one name="AuditAction" class="AuditAction" column="`AuditActionId`" not-null="true" fetch="join" />
<bag name="Percentages" fetch="join" access="readonly" inverse="true" lazy="false" table="tBenchmarkFxHedgeRatioHistory" cascade="all-delete-orphan" subselect="">
<key column="`BenchmarkFxHedgeHistoryId`" />
<one-to-many class="BenchmarkFxRuleRatioHistory" />
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Tests.DomainModel" assembly="Tests.DomainModel" xmlns="urn:nhibernate-mapping-2.2">
<class name="BenchmarkFxRuleRatioHistory" table="`tBenchmarkFxHedgeRatioHistory`" schema="`dbo`">
<composite-id>
<key-property name="NonBaseCurrencyCode" type="String" column="`NonBaseCurrencyCode`" />
<key-many-to-one name="HistoryEntry" class="BenchmarkFxHedgeRuleHistory" column="`BenchmarkFxHedgeHistoryId`" />
</composite-id>
<property name="Percentage" type="decimal" column="`PctHedgeBackToBase`" />
</class>
</hibernate-mapping>
Now I use these in the following code:
using(var session = DataMapperConfiguration.SessionFactory.OpenSession())
{
var sessionRule = session.Get<BenchmarkFxHedgeRule>(id);
var historyList = session.Query<BenchmarkFxHedgeRuleHistory>()
.Where(x => x.Rule == sessionRule).ToList();
Assert.AreEqual(2, historyList[0].Percentages.Count);
}
What happens is that sessionRule is correctly hydrated, but historyList does not have its Percentages property correctly hydrated. It keeps coming back as an empty list, but I expect it to have members in the list since there are matching rows in the database.
Any advice? What could I be doing wrong?
It turns out that the problem was that I declared the Percentages collection as an IList instead of an ICollection. Changing the declaration to ICollection<BenchmarkFxRuleRatioHistory> solves the problem.

nhibernate parent/child one-to-one mapping

I have two classes:
public class Code
{
public virtual Guid CodeId { get; set; }
public virtual string CodeValue { get; set; }
public virtual Guid EntryId { get; set; }
}
public class Entry
{
public virtual Guid EntryId { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Address { get; set; }
public virtual string Address2 { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string Zip { get; set; }
public virtual string Email { get; set; }
public virtual string Phone { get; set; }
public virtual string IpAddress { get; set; }
public virtual DateTime BirthDate { get; set; }
public virtual DateTime Created { get; set; }
public virtual bool OptIn { get; set; }
public virtual Code Code { get; set; }
}
I want nhibernate to automatically load/save the Code child property of the Entry object (which can be null and is linked by a foreign key "EntryId" in the Codes table), but I cannot figure out the mapping. The documentation at hibernate.org isn't loading for me right now, so could someone point me in the right direction with the mappings below?
<class name="Code" table="Codes">
<id name="CodeId">
<generator class="guid.comb"/>
</id>
<property name="CodeValue" />
<property name="EntryId"
</class>
<class name="Entry" table="Entries">
<id name="EntryId">
<generator class="guid.comb"/>
</id>
<property name="FirstName" />
<property name="LastName" />
<property name="Address" />
<property name="Address2" />
<property name="City" />
<property name="State" />
<property name="Zip" />
<property name="Email" />
<property name="Phone" />
<property name="BirthDate" />
<property name="OptIn" />
<property name="IpAddress" />
<property name="Created" />
</class>
I believe this article describes the possibilities very well:
http://ayende.com/Blog/archive/2009/04/19/nhibernate-mapping-ltone-to-onegt.aspx
You just don't need to "simulate" the bidirectionality, but that's easy to leave out.