Deletion of one-to-zero or one child record not working - nhibernate

I'm trying to map a couple of tables where the primary key in Bar is a foreign key to Foo i.e. a 1..0:1 relationship.
My mappings look like this:
class FooMapping : ClassMap<Foo>
{
public FooMapping()
{
Table("Foo");
Id(x => x.Id).Column("ID");
HasOne(x => x.Bar).Cascade.All();
}
}
class BarMapping : ClassMap<Bar>
{
public BarMapping()
{
Table("Bar");
Id(x => x.FooId).GeneratedBy.Foreign("Foo");
HasOne(x => x.Foo).Constrained();
}
}
The problem is that when I try to remove an instance of Bar by setting Foo.Bar = null and Bar.Foo = null, the record does not get deleted from the database.
What am I missing?

So basicly the problem is that you're using Cascade.All() in the mapping of Foo.
Instead of that you should be using Cascade.AllDeleteOrphan().
Cascade.All
when an object is save/update/delete, check the associations and save/update/delete all the objects found.
Cascade.AllDeleteOrphan
when an object is save/update/delete, check the associations and save/update/delete all the objects found. In additional to that, when an object is removed from the association and not associated with another object (orphaned), also delete it.

There is other dirty solution by making this relation with using HasMany and Cascade.AllDeleteOrphan.
class FooMapping : ClassMap<Foo>
{
public FooMapping()
{
Table("Foo");
Id(x => x.Id).Column("ID");
HasMany(x => x.Bar).KeyColumn("FooId").Cascade.AllDeleteOrphan();
}
}

Related

FluentNhibernate Map ValueObject

I have the following use case:
public class Object {
long Id
...
ISet<Tags> tags
}
public class Tag : IEquatable<Tag> {
string Label;
}
Object is an Aggregate Root and Tag a Value Object.
Both are stored in 2 different tables:
CREATE TABLE incident(id bigint, ...)
CREATE Table tag (object_id bigint References object(id), label varchar,...)
I'm trying to create the ClassMap using FluentNhibernate, which works well for object but I couldn't find a way to map it with Tag
public ObjectsMapping()
{
Id(x => x.Id).GeneratedBy.Assigned();
Version(x => x.ObjectVersion).Column("object_version");
HasMany(x => x.Tags).Inverse().Cascade.All().KeyColumn("object_id");
}
public TagsMapping()
{
CompositeId().KeyProperty(x => x.Label).KeyProperty(x => x.CreationTimestamp);
Map(x => x.Label);
Map(x => x.CreationTimestamp);
}
Any idea how to map that an entity that has a oneToMany relation with a ValueObject from another table ?
Basically I'm looking for an equivalient of Set() in NHibernate
Thank you
I found the solution:
In ObjectMapping:
HasMany(x => x.Tags).Component(x => { x.Map(k => k.Label); }).Table("tag");

How to map a string collection from another table in Fluent NHibernate?

I have an entity:
public class Foo
{
public virtual int Id;
public virtual IEnumberable<string> Bars;
}
And its mapping:
public class FooMapping : ClassMap<Foo>
{
public FooMapping()
{
Table("foo_table_in_database");
Id(x => x.Id, "Id");
HasMany(x => x.Bars)
.AsList()
.Table("bars_table_in_db")
.Element("BarId", m =>
{
m.Type<string>();
});
}
}
And an exception returned inside the entity insteaf of the expected result :(
base = {"could not initialize a collection: [Loya.Services.CouponsWeb.Promotion.LoyCouponCustomerGroups#2][SQL: SELECT loycouponc0_.Promotion_id as Promotion3_0_, loycouponc0_.LoyCustomerGroupId as LoyCusto1_0_, loycouponc0_.Index as Index0_ FROM loy_promotion__cu...
Database tables :
foo_table : *Id, other properties
bar_table : *FooId, *BarId
My aim is to get a List of BarId's (strings) in my Foo.
How do I map it properly?
I think you might need to specify the KeyColumn. I do something similar in one of my solutions and I would map the entities above as follows...
mapping.HasMany(x => x.Bars)
.Schema("Schema")
.Table("FooBars")
.Element("Bar")
.KeyColumn("FooID")
.ForeignKeyConstraintName("FK_FooBar_Foo")
.Not.Inverse()
.Cascade.All()
.Fetch.Select();
This will give a table called Schema.FooBars. It will have a FooID column (which is a foreign key back to the Foo table) and a Bar column which contains the value in your Bars collection.

Mapping properties from a foreign table twice in Fluent NHibernate

I have 2 tables like this: (Please note the non-standard db schema naming)
table T_Pen
TP_ID
TP_PrimaryColorID
TP_SecondaryColorID
...
table E_Color
EC_ID
EC_ColorName
...
And I want to create a mapping of the 2 tables to a domain object Pen using Fluent NHibernate.
class Pen
{
PenID;
PrimaryColorName;
SecondaryColorName;
...
}
How can I do that?
I don't think you would be able to Insert/Update anymore if you were to only reference the Name.
You could create a view of PenColour or hide the actual reference in your pen class and only expose the Name property.
class Pen
{
int PenID;
Color PrimaryColor;
Color SecondaryColor;
}
class Color
{
int ColorID;
string ColorName;
}
class ColorMap
{
Id(x => x.ColorID);
Map(x => x.ColorName);
}
class PenMap
{
Id(x => x.PenID);
References(x => x.PrimaryColor).Column("TP_PrimaryColorID");
References(x => x.SecondaryColor).Column("TP_SecondaryColorID");
}

Nhibernate Updating - Solutions for updating children on an entity?

Looking for some advice on how to update a collection on an entity. In a web app - we have a multiselect listbox allowing a user to assign and remove child entities from a list of available entities. The user would select the relevant children to associate with the parent. i.e. Product with multiple Categories it could belong to. Once the user is satisfied, they submit and we update the entities.
What is the preferred way to update(delete removed children, add new children) to the collection taking performance into account. I would not want to run several sql statements to fetch each child and add it to the parent.
Cheers
Mappings Attached:
public class ParentMap : EntityMapping<Parent>
{
public ParentMap()
{
Map(x => x.Name);
HasMany(x => x.Children)
.Cascade.AllDeleteOrphan()
.Access.LowerCaseField(Prefix.Underscore);
}
}
public class ChildMap : EntityMapping<Child>
{
public ChildMap()
{
References(x => x.Parent);
}
}
public abstract class EntityMapping<TEntity> : ClassMap<TEntity> where TEntity : EntityBase
{
protected EntityMapping()
{
Id(x => x.Id, "Id")
.UnsavedValue("00000000-0000-0000-0000-000000000000")
.GeneratedBy.GuidComb();
OptimisticLock.Version();
Version(entity => entity.Version);
}
}
Establish a cascade relation between parent and child entities and force it to act on all operations like update, delete, etc. You must define cascade behavior in you HBM mapping files. For more info: http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-mapping

NHibernate explicit fluent column mapping

I have a set of fluent object mappings that looks like this:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Map(x => x.Id);
Map(x => x.Status);
}
}
public class SpecialUserMap : SubClassMap<SpecialUser>
{
public SpecialUserMap()
{
Map(x => x.Property);
}
}
public class DirectoryMap : ClassMap<Directory>
{
public DirectoryMap
{
Map(x => x.Id);
HasMany(x => x.SpecialUsers).Where("Status = 0");
}
}
User is a join table, which SpecialUser joins against to get things like status. However, when I try to reference a SpecialUser in Directory's SpecialUsers collection, I get an error of "Undefined column 'Status'", as in the generated SQL, NHibernate tries to grab the Status column from the SpecialUser table, and not the User table.
Is there a way to explicitly tell NHibernate which table to get the Status column in the DirectoryMapping?
The Status property of a User / SpecialUser needs to map onto a single column in the database. You can't have it coming sometimes from User and sometimes from SpecialUser.
As a workaround, you could add a SpecialUserStatus property to SpecialUser, and then you could query on that easily.
That mappings looks right for table-per-subclass mapping, assuming that SpecialUser extends User. My guess is that it's a bug.