I'm using NHibernate Validator to perform validation. I'd like to call validation in the application services layer, passing an aggregate root. It works and traverses the graph with one exception.
It does not "reach" one of the transient objects in the aggregate root's collection. This is happening only if the collection is lazily loaded, and it hasn't been enumerated yet. >From what I've seen in NHV sources the collection is NH's PersistentGenericBag that is not initialized (true, because I haven't iterated over it, just added an item to it, which in turn adds some deferred insert operations). NHV skips validating it, since it would cause loading the collection from DB. The result is that my transient instance is not validated. Now the question is, is there any way to get transient objects from the collection without hydrating the whole collection? I would then change the NHV to do that. I think the AbstractEntityPersister does something like that to persist transient items without touching the whole collection. Or maybe I'm misusing NHV, and there is a way to validate transient objects in uninitialized collections..? What I want to do is a one Validate() call at the end of my app service method. Filip Zawada This is the basic setup of a proof-of-concept: [Whole project is @ http://www.megaupload.com/?d=AA919CHE - 3.0 MiB] <Program.cs> static class Program { static void Main() { Configuration cfg = new Configuration().Configure ("NHibernate.config"); FluentConfiguration fluentCfg = Fluently.Configure(cfg) .Mappings(mapping => mapping.FluentMappings.AddFromAssemblyOf<User>()); fluentCfg.ExposeConfiguration(BuildSchema); ValidatorEngine engine = new ValidatorEngine(); engine.Configure(); ISessionFactory sessionFactory = fluentCfg.BuildSessionFactory (); int id = 0; using (ISession session = sessionFactory.OpenSession()) { User user = new User { Mobile = "+48505111222" }; session.Save(user); id = user.Id; session.Flush(); } using (ISession session = sessionFactory.OpenSession()) { User user = session.Get<User>(id); User userWithInvalidMobile = new User { Mobile = "" }; user.Contacts.Add(new Contact { Name = "Contact1", ContactOwner = user, NumberOwner = userWithInvalidMobile }); InvalidValue[] errorzzz = engine.Validate(user); // should show 1 in the console, instead, we get a 0 Console.WriteLine(errorzzz.Count()); session.Flush(); } } private static void BuildSchema(Configuration config) { // just to create the database structure // provided the connection string in NHibernate.config is set correctly new SchemaExport(config).Create(false, true); } } </Program.cs> ----------------- <Domain.cs> public class User { public virtual int Id { get; set; } [NotEmpty, NotNull] public virtual string Mobile { get; set; } [Valid] public virtual IList<Contact> Contacts { get; set; } } public class Contact { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual User ContactOwner { get; set; } [Valid] public virtual User NumberOwner { get; set; } } public class UserMap : ClassMap<User> { public UserMap() { Id(u => u.Id, "UserId") .GeneratedBy.HiLo("10"); Map(u => u.Mobile); HasMany(u => u.Contacts) .AsBag().KeyColumnNames.Add("ContactOwnerFk") .Access.AsProperty() .Cascade.AllDeleteOrphan() .Inverse(); } } public class ContactMap : ClassMap<Contact> { public ContactMap() { Id(c => c.Id, "ContactId") .GeneratedBy .HiLo("10"); Map(c => c.Name); References(c => c.NumberOwner) .ColumnName("NumberOwnerFk") .Cascade.All(); References(c => c.ContactOwner) .ColumnName("ContactOwnerFk"); } } </Domain.cs> --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "nhusers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nhusers?hl=en -~----------~----~----~----~------~----~------~--~---
