I am trying to map several tables using Fluent Nhibernate. My tests are giving me the following error:
NHibernate.Exceptions.GenericADOException: could not initialize a collection: [FluentWeb.Domain.Employees.Orders#1]
I am trying to map a one to many relationship between Employees and Orders. Orders then has a many to many relation ship with Products (NorthWind). Here are my mappings.. Can someone give me a hand. All was working with HBMs
public class EmployeeMap : ClassMap<Employees>
{
public EmployeeMap()
{
Id(x => x.EmployeeID);
Map(x => x.FirstName);
Map(x => x.LastName);
Map(x => x.City);
Map(x => x.HireDate);
Map(x => x.Title);
HasMany(x => x.Orders)
.AsBag().WithForeignKeyConstraintName("EmployeeID")
.Inverse()
.Cascade.All();
}
}
public class OrdersMap : ClassMap<Orders>
{
public OrdersMap()
{
Id(x => x.OrderID);
Map(x => x.OrderDate);
Map(x => x.RequiredDate);
Map(x => x.ShippedDate);
References(x => x.Employee);
HasManyToMany(x => x.Products)
.Cascade.All()
.WithTableName("Order Details");
}
}
public class ProductsMap : ClassMap<Products>
{
public ProductsMap()
{
Id(x => x.ProductID);
Map(x => x.ProductName);
Map(x => x.UnitPrice);
HasManyToMany(x => x.Orders)
.Cascade.All()
.Inverse()
.WithTableName("Order Details");
}
}
Please let me know if more information is needed. Thanks for the help!
-Nick
Spaces in table names is usually a pretty bad idea. If you can't remove them, try surrounding the table names in backticks, which is NHibernate's database agnostic escaping mechanism.
.WithTableName("`Order Details`');
Related
Consider following mapping code please :
public sealed class BankMapping : ClassMap<Bank>
{
public BankMapping()
{
CompositeId()
.KeyProperty(x => x.SerialNumber, "SerialBankRef")
.KeyProperty(x => x.FinancialPeriodId, "FinancialPeriodRef");
Map(x => x.Code);
Map(x => x.Title);
Map(x => x.Comment);
Map(x => x.IsActive);
HasMany(x => x.BankBranchs).KeyColumns.Add(new[] { "SerialBankRef", "FinancialPeriodRef" });
}
}
And the BankBranch mapping code is :
public sealed class BankBranchMapping : ClassMap<BankBranch>
{
public BankBranchMapping()
{
CompositeId()
.KeyProperty(x => x.FinancialPeriodId, "FinancialPeriodRef")
.KeyProperty(x => x.SerialNumber, "SerialNumber");
Map(x => x.Code);
Map(x => x.Title);
Map(x => x.Comment);
Map(x => x.IsActive);
Map(x => x.Address);
Map(x => x.Fax);
Map(x => x.Telephone);
References(x => x.Bank).Columns(new[] { "SerialBankRef", "FinancialPeriodRef" });
}
}
As you can see the FinancialPeriodRef field acts as foreign key and part of composite key in the BankBranch mapping and NHibernate builds DB correctly and everything seems to be fine until I try to insert a record in the BankBranch table.
The error System.IndexOutOfRangeException : Invalid index 10 for this SqlParameterCollection with Count=10. which indicates I've mapped a field (FinancialPeriodRef) twice as FK and PK appears and I have no idea how to fix the problem.
I need FinancialPeriodRef in the BankBranch as part of primary key while it's absolutely equal to FinancialPeriodRef from Bank.
I need this field to establish unique constraint and also benefits of composite key is essential.
You need to use KeyReference rather than KeyProperty to describe composite foreign keys.
public BankBranchMapping()
{
CompositeId()
.KeyReference(x => x.FinancialPeriodId, "FinancialPeriodRef")
.KeyReference(x => x.SerialNumber, "SerialNumber");
...
}
I had the exact same problem as you and after an hour or so came across this post: https://stackoverflow.com/a/7997225/569662 which pointed me right.
I have two classes
public PartMap()
{
Id(x => x.ID).GeneratedBy.Guid();
HasOne(x => x.Stock)
.Cascade.All();
}
public Stock
{
Id(x => x.ID).GeneratedBy.Guid();
References(x => x.Part);
}
Part has only one stock, that's the reason i used HasOne.
The data is inserted ok, I have a part , a stock and they are saved ok.
My problem is when trying to delete I get an error that the stock foreing key to part was violated
"ORA-02292: integrity constraint (PRINERGY.FK121AD9E59966BE23) violated " .
I see the it tries to delete the part without deleting the related stock before.
How can I solve it?
It seems like a one-to-one bidirectional association. There are two ways how to map this association in NH (and FNH): primary key association and foreign key association. Your example is closer to foreign key association.
Foreign key association
public PartMap()
{
Id(x => x.Id).GeneratedBy.Guid();
References(x => x.Stock).Unique().Cascade.All();
Map(x => x.Name);
}
public StockMap()
{
Id(x => x.Id).GeneratedBy.Guid();
HasOne(x => x.Part).Cascade.All().PropertyRef("Stock");
Map(x => x.Name);
}
Primary key association
public PartMap()
{
Id(x => x.Id).GeneratedBy.Guid();
HasOne(x => x.Stock).Cascade.All();
Map(x => x.Name);
}
public StockMap()
{
Id(x => x.Id).GeneratedBy.Foreign("Part");
HasOne(x => x.Part).Constrained();
Map(x => x.Name);
}
For more details see http://fabiomaulo.blogspot.com/2010/03/conform-mapping-one-to-one.html.
i have the following code, which is supposed to give specific functionality but it isn't :S
anyway, here's my problem:
http://img525.imageshack.us/img525/1315/diagramp.png
here's the mapping code:
public class UsersMap : ClassMap<User>
{
public UsersMap()
{
this.Table("Users");
Id(x => x.UserName).GeneratedBy.Assigned();
Map(x => x.FirstName);
Map(x => x.LastName);
Map(x => x.Password);
Map(x =>x.EMail);
Map(x => x.Title);
Map(x => x.Division);
Map(x => x.Status);
HasManyToMany(x => x.Roles)
.Table("UserInRoles").ParentKeyColumn("Username")
.ChildKeyColumn("RoleId").AsBag().Inverse();
}
}
public class RolesMap : ClassMap<Role>
{
public RolesMap()
{
this.Table("Roles");
Id(x => x.ID).GeneratedBy.Assigned();
Map(x => x.RoleName);
HasManyToMany(x => x.Users)
.Table("UserInRoles").ParentKeyColumn("RoleId")
.ChildKeyColumn("Username").AsBag().Cascade.All();
}
}
my problem is when trying to (assign a Role for specific user) the UserName is added to table UserInRoles but the Role ID if it is already existing it will be removed from its corrosponding row and assigned to the new row, any idea ?
Have you looked making your ManyToMany work by convention?
Linked example actually refers to Roles and pretty much what you are trying to do here.
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.
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.