Fluent NHibernate "HasMany" classes in Configuration.ClassMappings - fluent-nhibernate

I'm trying to create a procedure to check the database structure, and for most of it I just look at "NHibernate.Cfg.Configuration.ClassMappings", but I can't find in the PersistentClass collection or each class properties the list of tables generated by fields mapped like this:
...
HasManyToMany(x => x.ChildrenListField);
...
How do I?

I guess what your are looking for are the CollectionMappings
foreach (var clazz in cfg.CollectionMappings)
....

Related

Get table names from Fluent Nhibernate

After you have setup your mappings in fluent nhibernate, is there a way of getting the table name for an entity from the class type?
I have read in regular nhiberante you can do something like cfg.GetClassMapping(typeof (Employee)). I would like to do the type of thing to retrieve the database table name.
Is this possible as standard or how would I go about this?
The fluent nhibernate way:
var userMetadata = sessionFactory.GetClassMetadata(typeof(SomeEntity)) as NHibernate.Persister.Entity.AbstractEntityPersister;
var cols = userMetadata.KeyColumnNames;
var table = userMetadata.TableName;
where sessionFactory is of type ISessionFactory.
Assuming you have done this at some point:
FluentNHibernate.Cfg.FluentConfiguration fluentConfig = FluentNHibernate.Cfg.Fluently.Configure();
Then all you have to do is this:
string tableName = fluentConfig.BuildConfiguration().GetClassMapping(typeof (One of your data entities)).Table.Name;
Worked great in my implementation of a generic "GetAllItems" routine.
Hi I'm using this to create Full Text Catalogs on M$ Sql Server, using almost same mechanism of FluentNhibernate mapping.
From Configuration I get a list of persistentClasses
this.persistenClasses = configuration.ClassMappings;
Next I search through this list to find my persistenClass class by its Generic type of mapping class
var genericDefinition = mappingClass.BaseType.GetGenericArguments()[0];
var matchedPersistClass = FindPersistedClassFrom(genericDefinition);
private PersistentClass FindPersistedClassFrom(Type genericDefinition)
{
return persistentClasses.FirstOrDefault(x => x.EntityName == genericDefinition.FullName);
}
So having persistentClass you easily have access to Table Name, properties, db fields, etc.
TableName = matchedPersistClass.Table.Name,
cfg.GetClassMapping(typeof(Employee)).Table.Name will also work, and seems to be much simpler.

How to Map a VIEW without unique identifing column with Fluent Nhibernate

i have readonly VIEWs in an existing Database and i'd like to get them with FHN. i tried mapping it the following way:
public class HhstMap : ClassMap<Hhst>
{
public HhstMap()
{
Table("HHST");
ReadOnly();
Id();
Map(x => x.Hkz);
Map(x => x.Kapitel);
Map(x => x.Titel);
Map(x => x.Apl);
Map(x => x.Hhpz);
}
}
but i got an error:
could not execute query
[ SELECT this_.id as id3_0_, this_.Hkz as Hkz3_0_, this_.Kapitel as Kapitel3_0_, this_.Titel as Titel3_0_, this_.Apl as Apl3_0_, this_.Hhpz as Hhpz3_0_ FROM HHST this_ ]
this is ok cause there is no ID Column, but how can i do mapping with Fluent without the ID?
You could retrieve the records as value objects (non-managed entities) instead of entities.
"14.1.5. Returning non-managed entities
It is possible to apply an IResultTransformer to native sql queries. Allowing it to e.g. return non-managed entities.
sess.CreateSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
.SetResultTransformer(Transformers.AliasToBean(typeof(CatDTO)))
This query specified:
the SQL query string
a result transformer
The above query will return a list of CatDTO which has been instantiated and injected the values of NAME and BIRTHNAME into its corresponding properties or fields. "
Maybe this can help you: Fluent nHibernate no identity column in tableā€¦?
EDIT:
Also, you could use a composite id, or maybe you need the latest version of Fluent Nhibernate?

nHibernate Collection Count

I have the following model which I have created and mapped with nHibernate.
Using lazy loading so I don't need to get the Vehicles for the Dealer at the start.
Public class Dealer
{
public virtual string Name { get;set;}
public virtual IList<Vehicles> Vehicles { get;set;}
}
Now let's assume the Dealer has thousands of vehicles.
If I do Dealer.Vehicles.Count then NH will select and pull all the data.
What is the best way to simply get a count? Is there any way in which I can get a count with out declaring A new property dealerCount within the Dealer Class?
Also there is a feature in Hibernate which I believe will be implemented in a newer version of NH called Extra Lazy Loading. Would this solve the problem?
extra lazy loading would issue sql instead of populating the collection for certain operations such as Count or Contains. In fluent mappings its used as:
HasMany(x => x.CollectionProperty).ExtraLazyLoad();
or HBM
<one-to-many lazy="extra" ...
It's only usefull if you have large collections and need the special behavior.
Use count projection (Projections.RowCount)

Nhibernate entity with multiple Many-To-Many lists of the same type?

Does anybody know how I would map an entity with two many-to-many collections of the same child type.
My database structure is this....
The "normal" relationship will be....
tbl_Parent
col_Parent_ID
tbl_Parent_Child_Xref
col_Parent_ID
col_Child_ID
tbl_Child
col_Child_ID
The alternative relationship is...
tbl_Parent
col_Parent_ID
tbl_Include_ParentChild_Xref
col_Parent_ID
col_Child_ID
tbl_Child
col_Child_ID
The entity and mapping look like this...
public partial class ParentEntity : AuditableDataEntity<ParentEntity>
{
public virtual IList<ChildEntity> Children { get; set; }
public virtual IList<ChildEntity> IncludedChildren { get; set; }
}
public partial class ParentMap : IAutoMappingOverride<ParentEntity>
{
public void Override(AutoMapping<ParentEntity> mapping)
{
mapping.Table("tbl_Parent");
mapping.HasManyToMany(x => x.Children)
.Table("tbl_Parent_Child_Xref")
.ParentKeyColumn("col_Parent_ID")
.ChildKeyColumn("col_Child_ID")
.Inverse()
.Cascade.All();
mapping.HasManyToMany(x => x.IncludedChildren)
.Table("tbl_Include_ParentChild_Xref")
.ParentKeyColumn("col_Parent_ID")
.ChildKeyColumn("col_Child_ID")
.Inverse()
.Cascade.All();
}
}
The error that I'm getting is
"System.NotSupportedException: Can't figure out what the other side of the many-to-many property 'Children' should be."
I'm using NHibernate 2.1.2, FluentNhibernate 1.0.
It seems FNH is confused because you seem to map the same object (ChildEntity) to two different tables, if I'm not mistaken.
If you don't really need the two lists to get separated, perhaps using a discriminating value for each of your lists would solve the problem. Your first ChildEntity list would bind to the discriminationg value A, and you sesond to the discriminating value B, for instance.
Otherwise, I would perhaps opt for a derived class of your ChildEntity, just not to have the same name of ChildEntity.
IList<ChildEntity> ChildEntities
IList<IncludedChildEntity> IncludedChildEntities
And both your objects classes would be identitical.
If you say it works with NH, then it might be a bug as already stated. However, you may mix both XML mappings and AutoMapping with FNH. So, if it does work in NH, this would perhaps be my preference. But think this workaround should do it.
You know I'm just shooting in the dark here, but it almost sounds like your ChildEntity class isn't known by Hibernate .. that's typically where I've seen that sort of message. Hibernate inspects your class and sees this referenced class (ChildEntity in this case) that id doesn't know about.
Maybe you've moved on and found the issue at this point, but thought I'd see anyway.
Fluent is confused because you are referencing the same parent column twice. That is a no-no. And as far as I can tell from the activity i have seen, a fix is not coming any time soon.
You would have to write some custom extensions to get that working, if it is possible.
To my great pity, NHibernate cannot do that. Consider using another ORM.

Fluent NHibnernate HasManyToMany with Index

I'm trying to map a many-to-many collection with Fluent NHibnernate. My model class has this property:
public virtual IList<Resource> Screenshots
{
get { return _screenshots; }
protected set { _screenshots = value; }
}
And my fluent mapping is:
HasManyToMany(x => x.Screenshots)
.AsList(x => x.WithColumn("Index"))
.Cascade.AllDeleteOrphan();
When I run my application, I get the following exception message:
The element 'list' in namespace
'urn:nhibernate-mapping-2.2' has
invalid child element 'many-to-many'
in namespace
'urn:nhibernate-mapping-2.2'. List of
possible elements expected: 'index,
list-index' in namespace
'urn:nhibernate-mapping-2.2'.
There should be a way to do this. Does anyone know what I am doing wrong?
The current FluentNHibernate syntax for this is as follows:
HasManyToMany(x => x.Screenshots)
.AsList(i => i.Column("`Index`"));
The index column defaults to Index, but that's a reserved word on SQL Server (and probably other databases too), so you must quote it with back-ticks.
Also, I'd recommend against setting a cascade on this relationship. Consider the following code:
x.Screenshots.Remove(s);
session.SaveOrUpdate(x);
NHibernate will correctly delete rows from the linking table even without a cascade specified. However, if you specify AllDeleteOrphan, then NHibernate will delete the row from the linking table and also delete Resource s. I doubt this is the behavior you want on a many-to-many relationship.