Mapping for multi-interface-inherited class in NHibernate - nhibernate

I have interface:
public interface IHasList<T>
{
IList<T> Items { get; set; }
}
And I want to map such class using one-to-many mapping to the lists:
public class Model : IHasList<A>, IHasList<B>
{
...
}
Can I do this? If yes, how to write mapping?

It's possible, but a little weird.
First, in order to declare this in C#, Model would look like this:
public class Model : IHasList<A>, IHasList<B>
{
IList<A> IHasList<A>.Items { get; set; }
IList<B> IHasList<B>.Items { get; set; }
}
So you need to make NHibernate understand that:
<bag name="IHasList<A>.Items" table="ModelItemA">
<key />
<one-to-many class="A" />
</bag>
<bag name="IHasList<B>.Items" table="ModelItemB">
<key />
<one-to-many class="A" />
</bag>
(I'm assuming A and B are mapped entities with a regular one-to-many relationship, change that to many-to-many or element and add cascade/inverse attributes as needed)
It's pretty clean, the mess is actually introduced by XML escaping. You'll also have to use full names for the classes.

Related

Mapping a column multiple times in Nhibernate

I have for example an entity. With the following properties:
public class Entity
{
public int CustomerId { get; set; }
public Customer { get; set; }
}
How can I map the CustomerId twice. Once for the int property and once for the many-to-one relationship ?
<many-to-one name="Customer" column="[CustomerId]" class="Customer"/>
<property name="CustomerId" column="[CustomerId]" type="Int64" />
Just this, doesn't work. I've already tried, making them readonly but no success.
One of them should be mapped as readonly (inser/udpate false), and referenced as formula
<many-to-one name="Customer" column="[CustomerId]" class="Customer"/>
<property name="CustomerId" formula="[CustomerId]" type="Int64" insert="false" update="false" />
Then it should be working correctly. Both properties then can be used for Select, Where... order by
You don't need to map CustomerId, you can access it through Customer.CustomerId. If you're using lazy loading, CustomerId will be populated in the proxy object so it's always available without triggering an additional select.
If you absolutely have to expose it, expose it as a nullable read only property:
public Customer { get; set; }
public int? CustomerId
{
get { return Customer == null ? (int?)null: Customer.CustomerId }
}

Map a column multiple times

I have a rather odd requirement in my fluent hibernate maps. I have an table(A) which has a compound foreign key relationship with another table(B). In the mapping for table A I would like to have both the object created from table B and access to the individual attributes of A which define the key. Is there any way to do that? I seem to get index out of range exceptions if I map the column twice.
I cannot just explore B for the attributes because the row in table B may not exist. I am painfully aware that there are some significant smells in the structure with which I'm dealing. Such is the fate of those who deal with legacy systems.
It's kinda possible, by hacking around a little.
We're going to define a domain that with a fake collection that we'll use to retrieve the single related element, if found:
public class Foo
{
public virtual BarKey BarKey { get; set; }
public virtual Bar Bar { get { return Bars.SingleOrDefault(); } }
protected virtual ICollection<Bar> Bars { get; set; }
}
public class Bar
{
public virtual BarKey Id { get; set; }
}
//this class must override Equals and GetHashcode. Implementation not shown.
public class BarKey
{
public virtual int X { get; set; }
public virtual int Y { get; set; }
}
The BarKey component contains the properties that are part of the key.
Now, the mapping:
<class name="Foo">
<id ...><generator .../></id>
<component name="BarKey">
<property name="X" />
<property name="Y" />
</component>
<bag name="Bars" inverse="true">
<key property-ref="BarKey">
<column name="X"/>
<column name="Y"/>
</key>
<one-to-many class="Bar"/>
</bag>
</class>
<class name="Bar">
<composite-id name="Id">
<key-property name="X" />
<key-property name="Y" />
</composite-id>
</class>
The property-ref attribute there tells NH to match those columns in Bar against the BarKey property of Foo instead of its Id.

How to setup Fluent NHibernate Many-To-Many automapping using Set instead of Bag?

http://www.codinginstinct.com/2010/03/nhibernate-tip-use-set-for-many-to-many.html
I want to do the way the author suggested for fluent nhibernate many-to-many but use automapping instead of HBM file.
Here are my two entities
public class User
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Iesi.Collections.Generic.Set<City> Cities { get; set; }
}
public class City{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Iesi.Collections.Generic.Set<User> Users { get; set; }
}
Tried with HashSet, IList, and Set. But when I looked at the HBM files generated by calling automapping output method:
var autoMappings = new AutoPersistenceModel().AddEntityAssembly(entityAssembly).Where(x => x.Namespace.EndsWith("Domain"));
autoMappings.WriteMappingsTo((#"C:\TEMP");
It's still bag type
<bag inverse="true" name="Users" table="MNUserCity" mutable="true">
<key>
<column name="CityId" />
</key>
<many-to-many class="MyApp.Entity.Domain.User, MyApp.Entity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<column name="UserId" />
</many-to-many>
</bag>
Is there any conventions/override I can use in Fluent NHibernate to alter the collection type for all the ManyToMany in the app domain? I looked at IHasManyToMany convention but no clue.
Anyone can help? Thanks.
BTW, I'm using latest build in http://github.com/jagregory/fluent-nhibernate
Changing the type of Users and Cities from Set to ISet should solve your issue.
As stated by James in this thread, "The automapper is very opinionated and inflexible, and it expects collections to be exposed as IList or ISet."

Complicated NHibernate component mapping

EDIT: I simplified the problem to leave only what really bothers me.
Hello all,
I am trying to make the following mapping.
In my database, I have a table called "ReportRowValue" containg the following columns:
RowNumber
ColumnNumber
StringValue
LongValue
DateValue
Value
In my code I want to get a more usable structure by creating several two classes from this one table. I guess this should be done using components and inheritance but I did not managed to create a working mapping file. What I want in code should look like this:
ReportRow
RowNumber
Values (collection of ReportValue below)
ReportValue (being an abstract class)
ColumnNumber
Value
ReportValueString / ReportValueLong / ReportValueDate (each one inheriting from ReportValue)
Value (each one having a Value property of its one type)
And that's about all!
Does anyone can point me how to create an nhibernate mapping file/files for doing that?
Thanks,
Meigetsu
There is couple of tools that maps and builds class for you one of them is
mygeneration
is the software http://sourceforge.net/projects/mygeneration/
In this page you find the templates that you need to run with the
softwarehttp://www.mygenerationsoftware.com/TemplateLibrary/Archives/?query=nhibernate
After you have this in the mygeneration tool you only connect to your DB and it will generated for you
Unfortunately, you can't have a polymorphic structure in a component. But I'm acutally not sure if you need it.
The following code is straight from my head, so it certainly has errors or missing things and wouldn't compile. But it should show the direction:
public class ReportRow
{
public int Id { get; private set; }
public IList<IReportValue> Values { get; private set; }
}
public interface IReportValue
{
public int Id{ get; set; }
public object UntypedValue { get; }
}
public abstract class ReportValue<T> : IReportValue
{
public int Id{ get; set; }
public T Value { get; set; }
public object UntypedValue { get { return Value; } }
}
public class ReportLongValue : ReportValue<long> {}
public class ReportStringValue : ReportValue<string> {}
public class ReportDateValue : ReportValue<DateTime>{}
Mapping:
<class ReportRow>
<id ...>
<bag name="Values" >
<key column="RowNumber"/>
<one-to-many class="IReportValue"/>
</bag>
</class>
<class name="IReportValue" abstract="true">
<id ...>
<subclass name="ReportLongValue">
<property name="Value" column="LongValue"/>
</subclass>
<subclass name="ReportStringValue">
<property name="Value" column="StringValue"/>
</subclass>
<subclass name="ReportDateValue">
<property name="Value" column="DateValue"/>
</subclass>
</class>

How does ORM solve bidirectional relationship between entities (NHibernate, for example)?

I'm writing a homework for my RDBMS class, I need to perform CRUD operations on quite simple domain, which is cyber sport championship.
Students are required to use ADO.NET. My question is how can I solve bidirectional relationship, for example 1:m (every championship has many matches, but every match belongs to only one exact championship)? It seems to me that there must be some technique for that.
And the most interesting part for me is - how does ORM like EF or NHibernate solve this situation?
In NHibernate, it is quite simple and straight-forward. Here's how the domain classes would look, followed by fluent mappings. This assumes you would use NHibernate to generate your schema. If you are mapping a legacy database, it is simple to set the column names and table names used.
public class Championship {
public virtual int Id { get; set; }
public virtual IList<Match> Matches { get; set; }
}
public class Match {
public virtual int Id { get; set; }
public virtual Championship Champioship { get; set; }
}
public class ChampionshipMap : ClassMap<Championship> {
public ChampionshipMap() {
Id(x => x.Id);
HasMany(x => x.Matches);
}
}
public class MatchMap : ClassMap<Match> {
public MatchMap () {
Id(x => x.Id);
References(x => x.Championship);
}
}
Have a look at Davy Brions Blog about building your own Data Access Layer. He talks about all those sort of challenges.
For something like many-to-many with Hibernate, you define the relationship. Here's an example (reference is here:
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<set name="people" inverse="true" table="PersonAddress">
<key column="addressId"/>
<many-to-many column="personId"
class="Person"/>
</set>
</class>
From the database side itself, for many-to-many relationship you will usually have a link table.
So we'd have:
PERSON
ADDRESS
PERSON_ADDRESS
The PERSON_ADDRESS table would contain person_id and address_id to link the two entities together. So one person could have many addresses, and a given address could potentially belong to more than one person or company.
For a 1:m relationship, it's good enough to have this:
PERSON
ADDRESS
In address, you would have the person_id column, but there could be many address records for a given person_id, giving you the 1:m capability.
For example in DataObjects.Net you can write following to get automatically associated Championship.Matches entity set and Match.Championship persistent field.
[HierarchyRoot]
public class Championship : Entity
{
[Field, Key]
public int Id { get; set; }
[Field, Association(PairTo="Championship")]
public EntitySet<Match> Matches { get; private set; }
}
[HierarchyRoot]
public class Match : Entity
{
[Field, Key]
public int Id { get; set; }
[Field]
public Championship Championship { get; set; }
}