Fluent nHibernate Mapping questions - many to many with data - fluent-nhibernate

this is my db:
tblGroups:
GroupID
GroupName
tblMembersInGroup
GroupID
MemberID
Rank
tblMembers
MemberID
Name
this is my Model:
class group
{
int groupid
string name
List<EnlistedMembers> myMembers;
}
class EnlistedMebmers
{
Member myMember;
int Rank;
}
class Member
{
int MemberID
string Name
}
I am not sure how to map this in FNH, as the Members class has no object that tells FNH who is the father.
I think the group mapping is obvious:
Table(tblGroup);
Id(x => x.groupid, "GroupID').GeneratedBy.Identity();
Map(x => x.name, "GroupName");
HasMany(x => x.myMembers).AsList().Inverse().Cascade.All();
What's next ?
how do I map enlistedmembers, with no identity object? and no group object ?
but with the extra rank data. the db has all the data, I need a way to create the classes right...
Thanks,
Dani

Is there a reason you need to map EnlistedMembers? If not, you could map Group.MyMembers like this:
HasManyToMany(z => z.MyMembers)
.AsList()
.Cascade.All()
.Table("tblMembersInGroup")
.ParentKeyColumn("GroupId")
.ChildKeyColumn("MemberId");

I suspect this may be a square peg for a round hole, but I'd look into SubClassing.
public class MemberMap : ClassMap<Member>
{
public MemberMap()
{
Table("tblMembers");
Id(x => x.MemberID);
Map(x => x.Name);
}
}
public class EnlistedMembersMap : SubclassMap<EnlistedMembers>
{
public EnlistedMembersMap()
{
Table("tblMembersInGroup");
Map(x => x.Rank);
}
}
You'll need to make EnlistedMembers inherit from Member. I'm also pretty sure it's going to bark about the composite key you have going in tblMembersInGroup. I don't have an answer for that... yet.

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.

Fluent Nhibernate - make References from children side only

I have Survey that HasMany Question that HasMany Option.
I want to create a reference from Option to Survey.
The problem is that Every time I want to create a new Survey with all of its children, I need to loop on all survey.Questions and loop on all survey.Questions.Options and set o each Option the Survey (or else Nhibernate will create a new Survey for each Option)
** I dont want to have IList<Option> on Survey if I do that it will solve the problem but it would be heavy and unusable **
public class SurveyMap : ClassMap<Survey>
{
public SurveyMap()
{
Id(x => x.Id).GeneratedBy.Identity();
HasMany(x => x.Questions).KeyColumn("SurveyId").Inverse().AsBag().Not.LazyLoad().Cascade.SaveUpdate();
}
}
public class QuestionMap : ClassMap<Question>
{
public QuestionMap()
{
Id(x => x.Id).GeneratedBy.Identity();
HasMany(x => x.Options).KeyColumn("QuestionId").Inverse().AsBag().Cascade.SaveUpdate();
}
}
public class OptionMap : ClassMap<Option>
{
public OptionMap()
{
Id(x => x.Id).GeneratedBy.Identity();
References(x => x.Survey).Column("SurveyId").Cascade.All();
}
}
It might be better to separate your reporting concerns from your applications business logic concerns. Use the mappings that you already have for your applications business logic, and provide a different interface into the data for your reporting requirements. You could use either HQL, SQL or new objects and maps for this.

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 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.