The implementation of a custom type is not an overkill, instead it is just
the way NH gives you to define what is correct/intelligent for you.
For me Int32 is more than enough and its default "unsaved-value" as zero is
more than enough. You are looking for a version with two possible
unsaved-value ('null' and zero)

On Tue, Nov 16, 2010 at 9:14 PM, Mike Pontillo <[email protected]> wrote:

> Hi Fabio,
>
>   Thanks for the response. A custom type seemed like overkill here
> since all I really want is a nullable Int32. I ended up doing three
> things to work around this problem:
>
>  - Made the version property in my POCO nullable (int?) to solve the
> problem where NHibernate found a "dirty" (but not really dirty) object
> in the database, since its version property was mistakenly set to null
>  - Made the version property in my mapping XML just an "int" (not sure
> if it necessary to call out that it's nullable in the mapping XML, but
> I got the exception noted below when I did -- it works when I leave
> out the type as well, of course.)
>  - Made the following code change (to fix the NullReferenceException
> when NHibernate tries to increment the null value in the database):
>
> --- Versioning.cs
> +++ Versioning.cs       (working copy)
> @@ -28,6 +28,11 @@
>            /// <returns>Returns the next value for the version.</returns>
>            public static object Increment(object version,
> IVersionType versionType, ISessionImplementor session)
>            {
> +            if(version == null)
> +            {
> +                version = versionType.Seed(session);
> +            }
> +
>            object next = versionType.Next(version, session);
>            if (log.IsDebugEnabled)
>            {
>
>   By the way, I also tested to verify that the 3rd change was really
> necessary. (Since I saw Seed() being used elsewhere, I wasn't sure if
> it would try again to increment a null value after I fixed my
> mappings.)
>
>   Also, in case anyone else is seeing this problem, the following
> exception is thrown when I try to specify the type of the version
> property in the XML as "int?":
>
> NHibernate.MappingException : Could not compile the mapping document:
> Example.hbm.xml
>  ----> NHibernate.MappingException : Could not determine type for:
> MyCompany.Model.int?, PROLIN.DAO, for columns:
> NHibernate.Mapping.Column(VERSION)
> at NHibernate.Cfg.Configuration.LogAndThrow(Exception exception) in
> Configuration.cs: line 340
> at NHibernate.Cfg.Configuration.AddDeserializedMapping(HbmMapping
> mappingDocument, String documentFileName) in Configuration.cs: line
> 528
> at NHibernate.Cfg.Configuration.AddValidatedDocument(NamedXmlDocument
> doc) in Configuration.cs: line 497
> at NHibernate.Cfg.Configuration.ProcessMappingsQueue() in
> Configuration.cs: line 1830
> at NHibernate.Cfg.Configuration.AddDocumentThroughQueue(NamedXmlDocument
> document) in Configuration.cs: line 1821
> at NHibernate.Cfg.Configuration.AddXmlReader(XmlReader hbmReader,
> String name) in Configuration.cs: line 1814
> at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream,
> String name) in Configuration.cs: line 644
> at NHibernate.Cfg.Configuration.AddResource(String path, Assembly
> assembly) in Configuration.cs: line 682
> at NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly) in
> Configuration.cs: line 761
> --MappingException
> at NHibernate.Mapping.SimpleValue.get_Type() in SimpleValue.cs: line 241
> at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.BindProperty(HbmVersion
> versionSchema, Property property, IDictionary`2 inheritedMetas) in
> RootClassBinder.cs: line 227
> at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.BindVersion(HbmVersion
> versionSchema, PersistentClass rootClass, Table table, IDictionary`2
> inheritedMetas) in RootClassBinder.cs: line 209
> at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.Bind(HbmClass
> classSchema, IDictionary`2 inheritedMetas) in RootClassBinder.cs: line
> 55
> at NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.AddRootClasses(HbmClass
> rootClass, IDictionary`2 inheritedMetas) in MappingRootBinder.cs: line
> 83
> at
> NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.AddEntitiesMappings(HbmMapping
> mappingSchema, IDictionary`2 inheritedMetas) in MappingRootBinder.cs:
> line 42
> at NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.Bind(HbmMapping
> mappingSchema) in MappingRootBinder.cs: line 29
> at NHibernate.Cfg.Configuration.AddDeserializedMapping(HbmMapping
> mappingDocument, String documentFileName) in Configuration.cs: line
> 520
>
>   This exception may be an error on my part rather than a bug, since
> I am not explicitly calling out nullable properties anywhere else in
> my mapping XML. (I imagine I was trying to do something unsupported,
> but I don't explicitly state types anywhere else in my mapping XML.)
> The quirk here is that for a version property (according to the
> reference manual I found at
> http://www.nhforge.org/doc/nh/en/index.html, section 5.1.7), the
> "type" parameter is "(optional - defaults to Int32)". I'm not sure why
> this wouldn't default to the type defined in the POCO for the version
> property. Also, the manual states "Version numbers may be of type
> Int64, Int32, Int16, Ticks, Timestamp, or TimeSpan (or their nullable
> counterparts in .NET 2.0)", so I assumed I could write "int?".
>
> Regards,
> Mike
>
> On Thu, Nov 11, 2010 at 6:12 AM, Fabio Maulo <[email protected]> wrote:
> > May be you have to know that you can implements your own type for the
> > version property following the rules of your legacy DB.
> >
> > --
> > Fabio Maulo
> >
> >
> > El 10/11/2010, a las 20:04, Mike Pontillo <[email protected]> escribió:
> >
> >> In case anyone was wondering,
> >>
> >>   I figured out the problem. I am trying to map a legacy database
> >> that uses version columns that are nullable. NHibernate threw
> >> exceptions when I defined the nullable types in my POCOs and the
> >> NHibernate XML (even though the manual stated that they were supported
> >> -- so likely a bug) so I defined them as "int". However, I didn't
> >> notice that some rows (very few - likely mistakes, or cases where
> >> someone hand-edited the data) in the database indeed have NULL values
> >> for the version column. If a query ever cached one of these NULL
> >> values, and NHibernate subsequently performed a dirty check, it will
> >> throw this exception.
> >>
> >>   If I have time, I'll write up a test case and try patching the code
> >> so NHibernate supports nullable version columns better. I think if
> >> NHibernate treated NULL version columns as if they had the value 0,
> >> this would fix the problem.
> >>
> >> Regards,
> >> Mike
> >>
> >> On Tue, Nov 9, 2010 at 5:30 PM, Mike Pontillo <[email protected]>
> wrote:
> >>> Greetings,
> >>>
> >>>   I am using NHibernate 3.0.0 beta 2, and am trying to evolve some
> >>> prototype code that was using the "session per call" anti-pattern to
> >>> use a "session per request" approach. I soon noticed that after
> >>> implementing the session sharing, my unit tests started failing with
> >>> the following exception:
> >>>
> >>> System.NullReferenceException : Object reference not set to an
> >>> instance of an object.
> >>> at NHibernate.Type.Int32Type.Next(Object current, ISessionImplementor
> >>> session) in d:\CSharp\NH\nhibernate\src\NHibernate\Type\Int32Type.cs:
> >>> line 77
> >>> at NHibernate.Engine.Versioning.Increment(Object version, IVersionType
> >>> versionType, ISessionImplementor session) in d:\CSharp\NH\nhibernate
> >>> \src\NHibernate\Engine\Versioning.cs: line 31
> >>> at
> >>>
> NHibernate.Event.Default.DefaultFlushEntityEventListener.GetNextVersion(FlushEntityEvent
> >>> event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default
> >>> \DefaultFlushEntityEventListener.cs: line 331
> >>> at
> >>>
> NHibernate.Event.Default.DefaultFlushEntityEventListener.ScheduleUpdate(FlushEntityEvent
> >>> event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default
> >>> \DefaultFlushEntityEventListener.cs: line 242
> >>> at
> >>>
> NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent
> >>> event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default
> >>> \DefaultFlushEntityEventListener.cs: line 45
> >>> at
> >>>
> NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent
> >>> event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default
> >>> \AbstractFlushingEventListener.cs: line 161
> >>> at
> >>>
> NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent
> >>> event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default
> >>> \AbstractFlushingEventListener.cs: line 60
> >>> at
> >>>
> NHibernate.Event.Default.DefaultDirtyCheckEventListener.OnDirtyCheck(DirtyCheckEvent
> >>> event) in d:\CSharp\NH\nhibernate\src\NHibernate\Event\Default
> >>> \DefaultDirtyCheckEventListener.cs: line 21
> >>> at NHibernate.Impl.SessionImpl.IsDirty() in d:\CSharp\NH\nhibernate\src
> >>> \NHibernate\Impl\SessionImpl.cs: line 1510
> >>>
> >>>   The failures happened at "random" times, such as when I was about
> >>> to execute a query and NHibernate would do a dirty check. So I added
> >>> asserts for session.IsDirty() to try to catch the problem earlier, but
> >>> I still don't see an obvious cause. The odd thing is, the version
> >>> property should not be incrementing, since I am only doing read-only
> >>> work within the session so far. For example, the following code fails:
> >>>
> >>>
> >>> Assert.IsFalse(session.IsDirty());
> >>>            var query = session.CreateQuery("from " + typeof(T).Name);
> >>>            var list = query.List<T>();
> >>>            Console.WriteLine(" HQL query: {0} " + typeof(T).Name + "
> >>> objects found", list.Count());
> >>>            Assert.AreEqual(_rowCount, list.Count()); // value cached
> >>> in test setup
> >>>            Assert.IsFalse(session.IsDirty());
> >>>
> >>>   I have been looking at this all afternoon, and tried to recreate
> >>> the problem by pasting similar unit test code into the
> >>> NHibernate.Test.VersionTest unit tests. (No luck yet.) Also, I tried
> >>> doing a "session.Clear()" before running this code, (which I thought
> >>> might solve the problem if there was stale data in the session) but it
> >>> had no effect.
> >>>
> >>>   I'm running out of ideas... does anyone have any thoughts on what
> >>> to look at next?
> >>>
> >>> Thanks,
> >>> Mike
> >>
> >> --
> >> 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]<nhusers%[email protected]>
> .
> >> For more options, visit this group at
> http://groups.google.com/group/nhusers?hl=en.
> >>
> >
> > --
> > 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]<nhusers%[email protected]>
> .
> > For more options, visit this group at
> http://groups.google.com/group/nhusers?hl=en.
> >
> >
>
> --
> 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]<nhusers%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/nhusers?hl=en.
>
>


-- 
Fabio Maulo

-- 
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.

Reply via email to