I have 3 tables that represents a many to many mapping.
Two tables with different ids and a third table with a composite key referencing the other two.
How can i map this using the classmap in nhibernate?
The following doesn´t work:
HasManyToMany(m =>
m.ListBlockStatus)
.Table("BlockTypeAction")
.ParentKeyColumn("IdBlockActionDefinition")
.ChildKeyColumn("IdBlockTypeCategory")
.Table("BlockTypeCategory")
.ParentKeyColumn("Id");
Found what i need, unfortunately the query in the end is not an inner join.
HasManyToMany(m => m.ListBlockStatus)
.Table("BlockTypeAction")
.ChildKeyColumns.Add("IdBlockActionDefinition")
.ParentKeyColumn("IdBlockTypeCategory")
.Cascade.All();
Related
I have a [User] table/class and a [Company] table/class and there is a link-table [UserCompany] between them.
When editing a User, beside basic information people also could change that user's access Companies, so I do the map like this in UserMap.cs:
HasManyToMany(u => u
.Companies)
.Cascade.SaveUpdate()
.Table("UserCompany")
.ParentKeyColumn("UserId")
.ChildKeyColumn("CompanyCode")
.Not.LazyLoad();
Also in CompanyMap.cs I set inverse like this:
HasManyToMany(c => c.Users)
.Inverse()
.Table("UserCompany")
.ParentKeyColumn("CompanyCode")
.ChildKeyColumn("UserId");
The problem now is: I could update [User] information/table, plus the linking data in [UserCompany] table. However, the Fluent Nhibernate also update the [Company] table which I don't need at all.
Is there any way I could let FN not update Company table?
To stop cascading updates just remove the
.Cascade.SaveUpdate()
from your Many-to-many mapping.
It could be a bit confusing. In comparison with the cascading used on <list>s and <map>s. In that case, the update is done directly on the child table (parent has more children... child contains the ParentId - cascade is reasonable to do operation on the child record)
But here we are working with a pair table. The relation is stored there. And this table will be always managed by NHibernate (implicit cascading).
The setting .Cascade.SaveUpdate() goes to other end of the many-to-many relation. To company table in our case. It could be handy.. but you can omit that and get everything running as expected.
When I add a Reference in my map the SQL generated fetches the foreign object with an outer left join. This gives good performance with only 1 SQL.
But when the referenced object does not exists on N rows NHibernate generates N extra queries to look up the non existing row. It should know it doesn't exists from the first query.
How do I disable this behavior?
References(x => x.Customer)
.Columns("c1", "c2")
.NotFound.Ignore();
Its a feature not a bug! https://nhibernate.jira.com/browse/NH-1001
I've got two objects a parent and a child list. In my fluent nhibernate mapping for the parent I want to load the list of the children.
However I want this to be conditional, a column in the child table is called "IsDeleted" and I only want to return the children where "IsDeleted" is false.
Is it possible to set up a mapping to do this? If not is it possible to do it in just standard nhibernate?
Thanks
Yes, you can use a Where constraint in Fluent NHibernate to map this. Somehting like:
HasMany(x => x.Children).Where("IsDeleted = 0");
The Where constraint should use SQL syntax not HQL. For tables that allow soft deletes it's probably easier to map a view that filters the deleted records out.
I want to create a many to many relationship, but I want to have in the new table(MessageReceivers) a unique contraint on both columns (AdvanceMessageId,UserId):
mapping.HasManyToMany(x => x.Receivers)
.WithParentKeyColumn("AdvanceMessageId")
.WithChildKeyColumn("UserId")
.Cascade.All()
.LazyLoad()
.WithTableName("MessageReceivers");
Thanks for help
Old post... but in case someone else arrives here looking for the answer:
You need to add .AsSet() to the HasManyToMany mapping definintion.
i.e.
mapping.HasManyToMany(x => x.Users)
.WithTableName("MessageReceivers")
.WithParentKeyColumn("UserId")
.WithChildKeyColumn("AdvanceMessageId")
.Inverse().AsSet();
This will setup an unique, composite primary key constraint on the link table that uses both columns.
(clustered index)
The down side is AsSet() cannont be used with collection properties of type IList, so no for loops without casting.
I have been using ICollection and instantiating them as HashSet for my applications and it works well.
More info on collection management with Fluent Nhibernate:
List: Ordered collection of entities, duplicate allowed. Use a .net IList in code. The index column will need to be mapped in NHibernate.
Set: Unordered collection of unique entities, duplicates not allowed. Use Iesi.Collection.ISet in code. It is important to override GetHashCode and Equals to indicate the business definition of duplicate. Can be sorted by defining a orderby or by defining a comparer resulting in a SortedSet result.
Bag: Unordered list of entities, duplicates allowed. Use a .net IList in code. The index column of the list is not mapped and not honored by NHibernate.
You should also map the inverse side of the relationship like
mapping.HasManyToMany(x => x.Users)
.WithTableName("MessageReceivers")
.WithParentKeyColumn("UserId")
.WithChildKeyColumn("AdvanceMessageId")
.Inverse();
In newest Fluent NHibernate you will have to change
WithTableName -> Table
WithParentKeyColumn -> ParentKeyColumn
WithChildKeyColumn -> ChildKeyColumn
I have a table A that has a references to a table B through a third table C. C contains the primary key of A and B. For each A there is at most one record in C. When I try to create a mapping for A such that I am referencing B, I use the References function, but it does not allow me to specify that the mapping goes through another table and not directly. What is the proper way to do that?
The only mapping that I know that could do that would be a HasManyToMany in the mapping of A :
HasManyToMany(x => x.B)
.WithTableName("C")
.WithParentKeyColumn("A_Id")
.WithChildKeyColumn("B_Id");
The problem is that the mapping is for A having a list of Bs, not just one. I don't know how you could do it to get only one in a clean way.
I believe I have found the answer in google code samples. In the mapping class, it is possible to write an additional:
WithTable("SomeTable", c => { c.Map(x => x.Col1); });