NHibernate mapping reference and reference id - nhibernate

I have simple task. I need map reference to properity and their ID to other properity.
If I use this map I get error:
"Additional information: Invalid index 24 for this
SqlParameterCollection with Count=24."
public CityMap()
{
Map(x => x.Name).Not.Nullable();
//Map(x => x.AddressID); //This line makes trouble
References(x => x.Address);

We can do it for read operation (I am quite happy to use this approach). Just, one of these properties must be insert="false" and update="false".
In fluent it should be like this:
...
Map(x => x.AddressID)
.Insert(false).Udpate(false)
// or just
// .ReadOnly()
;
References(x => x.Address);
We just have to decide which will be the readonly. Reference? or ValueType? I would make Reference editable, because then all NHibernate built in features will work (e.g. assign to transient object will properly later insert the just created ID)
Also check these for some more details check this or here.

Related

Map a collection of custom types on fluent nhibernate

I have a Custom Type on Fluent NHibernate and I need to map it to a collection of its type, using HasMany association. However, Fluent Nhibernate doesn't let me indicate on HasMany that its about a custom type like I do in my regular types.
This is my code:
HasMany(x => x.AvailablePaymentOptions)
.KeyColumn("OFFER_ID")
.Cascade.None()
.KeyNullable()
.Not.LazyLoad();
Any thoughts?
Thanks
Finish not using the custom type, but instead, mapping a component:
HasMany(x => x.AvailablePaymentOptions)
.Table("MY_TABLE")
.KeyColumn("MY_COLUMN")
.Component(component =>
{
//MAP YOUR CUSTOM TYPE HERE
})
.Cascade.None()
.KeyNullable()
.Not.LazyLoad();

Version does not increment when updating child item

If I read the documentation correctly if I have an Order entity mapped with a version column (incremented by nhibernate) then changes to orderlines should update the version number for the aggregate root (the Order). It does indeed do this when I add/remove orderlines, but if I only change, for example the quantity on an orderline the version of the order is not updated. Is this expected behavior?
I checked the NH source and it appears it only checks for dirty collections when trying to determine if version increment is necessary, and the collection will only be dirty when adding/removing items, not if any item in the collection is dirty.
I have the following mapping:
public class OrderMap : ClassMap<Order>
{
public OrderMap()
{
Id(c => c.Id).GeneratedBy.GuidComb();
Version(c => c.Version);
OptimisticLock.Version();
HasMany(x => x.OrderLines)
.Inverse()
.Cascade.AllDeleteOrphan();
}
}
public class OrderLineMap : ClassMap<OrderLine>
{
public OrderLineMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
Map(x => x.Quantity);
References(x => x.Order);
}
}
So my question is if this is expected behavior? That is that version will not update when modifying child entities only when the child collection is modified with remove/add. It sort of breaks the aggregate root concurrency model.
This is indeed expected behavior. There is a way to solve it using a event listener that can detect changes in children and traverse to the aggregate root and lock that optimistically (triggering a version change).
More information in this post by Ayende:
http://ayende.com/blog/4055/nhibernate-automatic-change-tracking-for-aggregate-roots-in-ddd-scenarios

Fluent Nhibernate - Generate a non-primary-key sequence generated value

I have an entity mapping quite similar to this one.
public class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
Id(x => x.Id);
Map(x => x.Code);
Map(x => x.Name);
Map(x => x.Description);
}
}
I'd like to know if there's any possible way to have the Code field (which is not part of the Primary Key) autogenerated by a sequence. There's a GeneratedBy property, but it's only an IdentityPart class member.
I don't see how using Listeners makes it any easier to use a built-in method for using sequence generators for non-ID columns.
However, if the only solution is to hook into OnPreInsert, making a direct query to the DB & invoke the sequence and get its value, then I suppose I'll have to live with it.
Is this how you solved the issue, Mauro?
Edit:
posted the question on the nHibernate & FluentNHibernate google groups:
https://groups.google.com/group/nhusers/browse_thread/thread/35d37b9abf3566f0
https://groups.google.com/group/fluent-nhibernate/browse_thread/thread/35d37b9abf3566f0
You need to use SaveOrUpdateEventListeners. See here to see Jake's reply for how to get it working for Fluent.

Fluent Nhibernate Order-By on Collection

If I have a collection mapped in Fluent NHibernate and I want to apply an order to that collection how do I do that?
Eg:
HasMany(x => x.PastDates)
.AsBag().Cascade
.SaveUpdate()
.KeyColumnNames.Add("EventId")
.Where(e => e.DateFrom < DateTime.Now.Date)
.Inverse();
I'm looking for the equivalent of the order-by attribute in HBM files.
Thanks
Fluent NHibernate now has an OrderBy method which you can use:
HasMany(x => x.PastDates)
.AsBag().Cascade
.SaveUpdate()
.KeyColumnNames.Add("EventId")
.Where(e => e.DateFrom < DateTime.Now.Date)
.Inverse()
.OrderBy("ColumnName DESC");
It appears that the "order-by" attribute is not in the FluentNHibernate API. I don't see an issue for it so this may be a conscious omission. You should be able to add it using SetAttribute but this user was unable to get it to work.
HasMany(x => x.PastDates)
.AsBag().Cascade
.SaveUpdate()
.KeyColumnNames.Add("EventId")
.Where(e => e.DateFrom < DateTime.Now.Date)
.Inverse()
.SetAttribute("order-by", "column_name");
Be aware that setting order-by may change the collection type that NHibernate uses; however this does not apply for bags.

Set up caching on entities and relationships in Fluent Nhibernate?

Does anyone have an example how to set up and what entities to cache in fluent nhibernate. Both using fluent mapping and auto mapping?
And the same for entity relationships, both one-to-many and many-to-many?
I have been working a a similar situation, where I just want to cache specific elements, and want these elements to be loaded once on start up, and kept in cache, until the application is shut down. This is a read only cache, and is used to populate a list of countries, so that a user can select their country from the list.
I used fluentNhibernate Mappings, and defined Country my class with Cache.readonly()
public class CountryMap : ClassMap<Country> {
public CountryMap() {
Schema("Dropdowns");
Cache.ReadOnly();
// Class mappings underneath
}
}
My user class map looks like this:
public class UserMap : ClassMap<User> {
Id(x => x.Id).Column("UserId");
Map(x => x.FirstName);
Map(x => x.LastName);
References(x => x.Country)
.Column("CountryId");
}
I manually configure Fluent Nhibernate to use Second level cache. So in my fluent Confuguration I have:
var sessionFactory = Fluently.Configure()
.Database (...) // set up db here
.Mappings(...) //set up mapping here
.ExposeConfiguration(c => {
// People advice not to use NHibernate.Cache.HashtableCacheProvider for production
c.SetProperty("cache.provider_class", "NHibernate.Cache.HashtableCacheProvider");
c.SetProperty("cache.use_second_level_cache", "true");
c.SetProperty("cache.use_query_cache", "true");
})
.BuildSessionFactory();
I have checked in SQL profiler, and when I get a list of countrys for a user, the are loaded once, and I get cache hits after every other request. The nice thing is that when displaying the users country name, it loads from the cache, and does not make a request to the database. I got some tips from this posting by Gabriel Schenker. Hope that helps? If you found a better/proper way, please let me know? Thanks!