Nhibernate Component Mapping : Parent Object null in Value Object while querying from database - nhibernate

I am mapping my value Object Item as component withthe folowing mapping configuration
{
Table("Product");
Not.LazyLoad();
Id(x => x.Id, "id");
Map(x => x.Number, "number");
Map(x => x.Name, "name");
Map(x => x.Description, "description");
Map(x => x.Status, "status");
HasMany(x => x.ItemLines).Component(
m =>
{
m.Map(x => x.ItemId, "itemid");
m.Map(x => x.Qty, "quantity");
}).Table("productitems").KeyColumn("itemid");
}
Class structure
public class ItemLine
{
public Product Product { get; set; }
public Guid ItemId { get; set; }
public int Qty { get; set; }
public ItemLine()
{
}
public ItemLine(Product product, Guid itemId, int qty)
{
Product = product;
ItemId = itemId;
Qty = qty;
}
//Equality and GetHashCode implemented.....
}
I am able to insert data to Database but while retrieving back by Product Id, the Product property in Item Line is null.
Do I need to pass any References in Mapping>
Please help
Thank you,
Mar

Ok. Solved by trial and error.
Add m.ParentReference(x => x.Product);
{
Table("Product");
Not.LazyLoad();
Id(x => x.Id, "id");
Map(x => x.Number, "number");
Map(x => x.Name, "name");
Map(x => x.Description, "description");
Map(x => x.Status, "status");
HasMany(x => x.ItemLines).Component(
m =>
{
m.Map(x => x.ItemId, "itemid");
m.Map(x => x.Qty, "quantity");
m.ParentReference(x => x.Product);
}).Table("productitems").KeyColumn("itemid");
}
hope this helps someone.

Related

How is a Fluent Nhibernate Reference / HasMany relationship supposed to work?

I have two tables setup with a reference and hasmany relationship. When the Xref.SaveOrUpdate() is called an "Invalid index 7 for this SqlParameterCollection with Count=7." exception is thrown. I get the feeling I'm not setting up the HasMany and References correctly. What should I be doing differently?
public class PortalPhysicianMap : ClassMap<PortalPhysician>
{
public PortalPhysicianMap()
{
Table("PortalPhysicians");
Id(x => x.PhysicianRno).GeneratedBy.Identity();
Map(x => x.A1PhysicianRno);
Map(x => x.LastName);
Map(x => x.FirstName);
Map(x => x.TitleName);
Map(x => x.SuffixName);
Map(x => x.CorrName);
Map(x => x.Specialty);
Map(x => x.Institution);
Map(x => x.Addr1);
Map(x => x.Addr2);
Map(x => x.City);
Map(x => x.State);
Map(x => x.PostalCode);
Map(x => x.Country);
Map(x => x.Phone);
Map(x => x.Fax);
Map(x => x.InactiveDt);
Map(x => x.CreatedDate, "CreatedDt");
Map(x => x.UpdatedDate, "UpdatedDt");
HasMany(x => x.Xrefs)
.KeyColumn("A1PhysicianRno");
//.Cascade.All();
}
}
public class PortalLoginPhyXrefMap : ClassMap<PortalLoginPhyXref>
{
public PortalLoginPhyXrefMap()
{
Table("PortalLoginPhyXref");
Id(x => x.XrefRno).GeneratedBy.Identity();
Map(x => x.LoginRno);
Map(x => x.A1PhysicianRno);
Map(x => x.UserName);
Map(x => x.UserRole);
Map(x => x.InactiveDt);
Map(x => x.CreatedDate, "CreatedDt");
Map(x => x.UpdatedDate, "UpdatedDt");
References<PortalPhysician>(x => x.Login)
.Column("LoginRno");
}
}
using (ISession s = Env.dbPortal.OpenSession())
{
try
{
using (ITransaction Trans = s.BeginTransaction())
{
Trans.Begin();
foreach (PortalLogin Login in lstLogins)
{
if (Login.UserName != null)
{
Login.SaveOrUpdate(s);
foreach (PortalLoginPhyXref Xref in Login.Xrefs)
{
Xref.LoginRno = Login.LoginRno;
Xref.SaveOrUpdate(s);
}
}
}
Trans.Commit();
}
}
catch (Exception Ex)
{
frmError.Show(Ex);
}
}
Additional code showing what happens in the SaveOrUpdate()
public class PortalLoginPhyXref : BaseRec
{
public virtual void SaveOrUpdate(ISession Sess)
{
base.SaveOrUpdate(Sess, XrefRno);
}
}
public abstract class BaseRec
{
public virtual DateTime CreatedDate { get; set; }
public virtual string CreatedUserID { get; set; }
public virtual DateTime? UpdatedDate { get; set; }
public virtual string UpdatedUserID { get; set; }
public virtual void SaveOrUpdate(ISession Sess, int Rno)
{
SaveOrUpdate(Sess, (Rno == 0));
}
public virtual void SaveOrUpdate(ISession Sess, string ID)
{
SaveOrUpdate(Sess, (ID == null));
}
private void SaveOrUpdate(ISession Sess, bool Save)
{
if (Save)
{
CreatedDate = DateTime.Now;
CreatedUserID = Env.UserID;
}
UpdatedDate = DateTime.Now;
UpdatedUserID = Env.UserID;
Sess.SaveOrUpdate(this);
}
}
You are mapping the same column twice in your mapping above. That is what generally causes the Invalid index 7 for this SqlParameterCollection with Count=7 error.
Here is an example of where you are doing this:
Map(x => x.LoginRno);
References<PortalPhysician>(x => x.Login)
.Column("LoginRno");
You should not be doing Map(x => x.LoginRno)
Login.SaveOrUpdate(s); // save or update transient login object with all referenced objects
foreach (PortalLoginPhyXref Xref in Login.Xrefs)
{
Xref.LoginRno = Login.LoginRno;
// Xref.SaveOrUpdate(s); // They'll update when you close transaction.
}

Fluent Nhibernate Many-to-Many mapping with extra column

I want to map sth like this using fluent Nhibernate but I am not sure how to map the inventory table
This is the tables I have :
Product (Id,Name, ...)
Warehouse(Id, Name, ...)
Inventory(Product_id, Warehouse_id, StockInHand)
and Mappings like below
Public ProductMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table("Inventory");
}
public WarehouseMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Products)
.Cascade.All()
.Table("Inventory");
}
The problem I face is that how can I map the StockInHand (how should the inventory model mapping?).
or are there other way to model this scenario ?
I have read some existing questions but not yet get clear understand what to do.
Thanks
Your relationship is not a many-to-many as far as NHibernate is concerned. A true many-to-many has no additional columns, such as StockInHand in your example.
You have to map this as two one-to-many relationships, and map Inventory as an entity.
Something like (i've skipped the other properties):
public class Product
{
public List<Inventory> Inventory { get; set; }
}
public class Warehouse
{
public List<Inventory> Inventory { get; set; }
}
public class Inventory
{
public Product Product { get; set; }
public Warehouse Warehouse { get; set; }
public bool StockInHand { get; set; }
}
public ProductMap() {
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Inventory)
.Cascade.All()
.Inverse()
.Table("Inventory");
}
public WarehouseMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Inventory)
.Cascade.All()
.Inverse()
.Table("Inventory");
}
public InventoryMap()
{
CompositeId()
.KeyReference(x => x.Product, "Product_id")
.KeyReference(x => x.Warehouse, "Warehouse_id")
Map(x => x.StockInHand);
}

Abort due to constraint violation columns GroupId, idx are not unique

I'm using FluentNHibernate and have done a many-to-many mapping but when I try to save my entity I get the following error:
NHibernate.Exceptions.GenericADOException: NHibernate.Exceptions.GenericADOException
: could not insert collection: [Test.Entities.Recipient.Groups#b6815d34-f436-4142-9b8e-1bfcbf25509e][SQL: SQL not available]
---- System.Data.SQLite.SQLiteException : Abort due to constraint violation
columns GroupId, idx are not unique
Here is my mapping:
public class GroupMap : ClassMap<Group>
{
public GroupMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.Name);
Map(x => x.SenderName);
Map(x => x.Created);
HasManyToMany(x => x.Recipients)
.AsList()
.WithTableName("groups_recipients")
.WithParentKeyColumn("GroupId")
.WithChildKeyColumn("RecipientId")
.LazyLoad()
.Cascade.AllDeleteOrphan();
}
}
public class RecipientMap : ClassMap<Recipient>
{
public RecipientMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.Firstname);
Map(x => x.Lastname);
Map(x => x.Phone);
Map(x => x.Email);
HasManyToMany(x => x.Groups)
.AsList()
.WithTableName("groups_recipients")
.WithParentKeyColumn("RecipientId")
.WithChildKeyColumn("GroupId")
.LazyLoad().Cascade.None();
}
}
The problem seems to have something to do with the relationship tables id but I can't figure out how to solve it.
Cheers,
nandarya
Using AsList() was not a good idea. Should be AsBag(). And everything seems to work.

Fluent NHibernate Mapping Error (Id column)

I'm getting a mapping error in Fluent NHibernate. Why is it still looking for _id when I have specified the column explicitly?
Invalid column name 'Account_id'.
[GenericADOException: could not initialize a collection: [ProtoStack.Business.Entities.Account.LedgerEntries#1][SQL: SELECT ***ledgerentr0_.Account_id*** as Account5_1_, ledgerentr0_.Id as Id1_, ledgerentr0_.Id as Id43_0_, ledgerentr0_.LedgerEntryDate as LedgerEn2_43_0_, ledgerentr0_.Amount as Amount43_0_, ledgerentr0_.AccountId as AccountId43_0_ FROM dbo.LedgerEntry ledgerentr0_ WHERE ledgerentr0_.Account_id=?]]
I have explicitly specified that the column is "AccountId".
public class AccountMap : ClassMap<Account>
{
public AccountMap()
{
Table("dbo.Account");
Id(x => x.Id)
.Column("Id");
Map(x => x.Code);
Map(x => x.Name);
Map(x => x.Description);
Map(x => x.Category);
References(x => x.Group)
.Column("AccountGroupId");
HasMany(x => x.LedgerEntries)
.Inverse()
.Cascade.All();
}
}
public class LedgerEntryMap : ClassMap<LedgerEntry>
{
public LedgerEntryMap()
{
Table("dbo.LedgerEntry");
Id(x => x.Id)
.Column("Id");
References(x => x.Account)
.Column("AccountId");
Map(x => x.LedgerEntryDate);
Map(x => x.Amount);
}
}
Am I missing something?
My bad. I was missing KeyColumn.
public class AccountMap : ClassMap<Account>
{
public AccountMap()
{
Table("dbo.Account");
Id(x => x.Id)
.Column("Id");
Map(x => x.Code);
Map(x => x.Name);
Map(x => x.Description);
Map(x => x.Category);
References(x => x.Group)
.Column("AccountGroupId");
HasMany(x => x.LedgerEntries)
.KeyColumn("AccountId")
.Inverse()
.Cascade.All();
}
}
Works now.

Fluent Nhibernate composed entity, specify foreign key

I have a Fluent Nhibernate map like :
public class UserMap : ClassMap<PortalUser>
{
public UserMap()
{
WithTable("aspnet_Users");
Id(x => x.Id, "UserId")
.GeneratedBy.Guid();
Map(x => x.Name, "UserName");
Map(x => x.Login, "LoweredUserName");
WithTable("LdapUsers", m => m.Map(x => x.FullName, "FullName"));
}
}
My foreign key column in table "LdapUser" is UserId but the select that gets generated is going to look for a "PortalUserId".
Is there a way to specify the relation key direcly?
Try this:
...
WithTable("LdapUsers", m => {
m.Map(x => x.FullName, "FullName");
m.WithKeyColumn("UserId");
});