How can I intercept/prevent a property from being modified with (fluent) NHibernate? - nhibernate

If I have a model (class) called Employee, how can I intercept/modify property changes?
For example:
Employee e = session.Get<Employee>(1);
e.Status = EmployeeStatus.Fired;
How can I intercept e.Status from being modified and either change it to a different value or throw an error, etc?
I know I can use events (ie. IPreUpdateEventListener) to modify the state but I'd like to do it immediately when a property is being assigned/modified if possible.

You can achieve this behavior using NHibernate Interceptors, take a look to this article.

Related

nHibernate3 + FluentNHibernate - "CreateDate" member not available on Update

My domain objects have a "CreateDate" and "ModidfyDate" members (DateTime).
When a user update a domain object (Asp.Net MVC) my view model does not hold these values. (It's to be set in my repository "Create" and "Update" methods)
So when I Update an object, I do not have the "CreateDate" available and therefore the Update method will fail.
I seems to have 2 options, and I don't like either:
1) Have my viewmodel tag along the "CreateDate" property (hidden field in form) so I have the original CreateDate available.
2) Or, in my "Update" repository method, first get the original record from the database and set the object I'm about to update's CreateDate member (an unnecessary call to the db)
What is the "normal" way to work with this?
A nice way to handle CreateDate and ModifyDate would be by using NHibernate's event listeners.
Here are some samples on how to create simple auditing using IPreInsertEventListener and IPreUpdateEventListener:
http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener
http://nhforge.org/wikis/howtonh/creating-an-audit-log-using-nhibernate-events.aspx
On a side note, you shouldn't have problems with CreateDate on your Update method. How does your Update method look like?
The usual workflow is to get your view model in POST ActionMethod, load the entity object from the database using NHibernate's ISession, or your custom repository and then map your properties from the view model to the entity, either by hand, or using a tool like AutoMapper. Properties like CreateDate should be ignored in the viewmodel to entity mapping.

LINQ and Static ObservableCollection

This will probably be a basic questions for the LINQ & architecture experts however I am failing to understand a problem i've encounted when trying to update a 'Static ObservableCollection.
Me.Grid1.ItemsSource = ContactList
Me.Grid2.ItemsSource = From s In ContactList Where s.ContactTypes.Any(Function(t) t.ContactTypeName = "Christmas List")
If I add a new Contact with the ContactType "Christmas List" to the ContactList ObservableCollection, Grid1 reflects the additional Contact however Grid2 does not reflect the change unless I rebind.
Anyway to Reflect the change in Grid2 to show the new Contact with the queried ContactType
Grid2 is actually binding to an IEnumerable(Of Contact) instead of an Observable Collection. That's why the change isn't reflected in Grid2. You need to cause your Linq query to reexecute using an event or INotifyPropertyChanged.
It could be happening due to the deferred execution nature of LINQ query. The values are fetched only when, you start enumerating over the result set. That is why, you have to rebind the data source, to see the change. Try adding ToList(), method at the end of the query. For e.g.
Me.Grid2.ItemsSource = From s In ContactList Where s.ContactTypes.Any(Function(t) t.ContactTypeName = "Christmas List").ToList();
You need my ObservableComputations library. Using this library you can code like this:
Me.Grid2.ItemsSource = ContactList.Filtering(c => c.ContactTypes.ContainsComputing("Christmas List").Value);
Filtering extention method returns instance of ObservableCollection and reflects all the changes in the ContactList collection and ContactTypes collection. Writing the code above, I assumed contactContactTypes id ObservableCollection. If this is not so, then you can code:
Me.Grid2.ItemsSource = ContactList.Filtering(c => c.ContactTypes.Contains("Christmas List"));
In this case do not forget to add the implementation of the INotifyPropertyChanged interface to Contact class, so that the result ObservableCollection reflects the change of contact.ContactTypes property.

Knowing child collections count without loading them in NHIbernate

I'm using NHibernate with FluentNH. I've a simple class called PostCategory and it contains a collection of Posts. The PostCategory class contains a property called TotalActivePosts. When I load all the PostCategories I want the no. of active posts for each category to be populated in this property. How I can do that? Any help is greatly appreciated.
Vijaya Anand
The way I did it is by using a computed property. see item no. 5- arbitrary SQL.
you could use something like:
Select Count(*) from Posts where PostCategoryId = Id And IsActive = 1
see also this question
You can either do what sJhonny recommends or use the lazy="extra" attribute on the mapping. That way you can just do Posts.Count to get just the count without loading all of the entities.
See this SO question:
NHibernate Lazy="Extra"

validation based on attributes in metadata class

I am performing validation based on attributes in metadata.cs file. I am using Entity framework 4.0 and using wcf ria services. I want to know what is the equivalent of Page.IsValid in asp.net in silverlight? How do i ensure that the entity is in correct state before saving it? If i do not ensure this an exception fires which looks very ugly. I found a property named entityName.ValidationErrorCount so if my entity is named User i do objUser.ValidationErrorCount is less than equal to 0 i save it. Problem with this approach is if the user doesn't enter value in any of the textbox then subsequently all the values in the entity are null. So ValidationErrorCount property returns 0 because all are null values and thus my program tries to save the entity but naturally the entity is in incorrect state so exception fires. How do i get past this problem?
I hope i am clear. If not, please let me know. Thanks in advance :)
You can validate an entity using the Validator class (from the System.ComponentModel.DataAnnotations
namespace), like so (where entity is a reference to the entity to be validated):
List<ValidationResult> validationResults = new List<ValidationResult>();
ValidationContext validationContext = new ValidationContext(entity, null, null);
bool isValid = Validator.TryValidateObject(entity, validationContext, validationResults, true);
Alternatively, are you using the DataForm control? If so, there's an even easier way to check whether the current item is valid, by calling the ValidateItem() method on the DataForm. This will return a boolean indicating whether the current item is valid (you can also check the IsItemValid property of the DataForm). It will also update the bound controls to show their validation status. If you're not using the DataForm, then it will certainly make it easier if you can. Otherwise, simply add the validation results to the entity's ValidationErrors property:
foreach (ValidationResult result in validationResults)
entity.ValidationErrors.Add(result);
Hope this helps...
Chris

NHibernate: How to get mapped values?

Suppose I have a class Customer that is mapped to the database and everything is a-ok.
Now suppose that I want to retrieve - in my application - the column name that NH knows Customer.FirstName maps to.
How would I do this?
You can access the database field name through NHibernate.Cfg.Configuration:
// cfg is NHibernate.Cfg.Configuration
// You will have to provide the complete namespace for Customer
var persistentClass = cfg.GetClassMapping(typeof(Customer));
var property = persistentClass.GetProperty("FirstName");
var columnIterator = property.ColumnIterator;
The ColumnIterator property returns IEnumerable<NHibernate.Mapping.ISelectable>. In almost all cases properties are mapped to a single column so the column name can be found using property.ColumnInterator.ElementAt(0).Text.
I'm not aware that that's doable.
I believe your best bet would be to use .xml files to do the mapping, package them together with the application and read the contents at runtime. I am not aware of an API which allows you to query hibernate annotations (pardon the Java lingo) at runtime, and that's what you would need.
Update:
Judging by Jamie's solution, NHibernate and Hibernate have different APIs, because the Hibernate org.hibernate.Hibernate class provides no way to access a "configuration" property.