Fabio,

If we do this, it is true that all versions of the Header would be
read back, correct?  This is something we would like to avoid if
possible since only two are necessary in most use cases.

I think I may have a way to do this, thanks to everyone's help:

public class Header
{
    public virtual int HeaderId { get; set; }
    public virtual Version LatestVersion { get; set; }
    public virtual Version LatestApprovedVersion { get; set; }

    // load all versions EXCEPT the latest and latest approved into
OldVersions
    // since we want them to be loaded independently of version
history
    protected virtual List<Version> OldVersions { get; set; }

    // not mapped by NH
    public virtual IEnumerable<Version> AllVersions {
    get
    {
         if(this.LatestApprovedVersion != null) yield return
this.LatestApprovedVersion;
         yield return this.LatestVersion;

         foreach(var version in this.OldVersions) yield return
version;
    }
    // other members
}

It seems a little clunky, but I think it would work and provide all of
the desired benefits.  Mapping should be simple and straightforward,
the latest and LA versions should be able to be loaded independently
of old versions, the old and latest approved versions could be
prohibited from being updated, while allowing the latest version to be
updated, and all of the reverse references from each Version to the
Header would refer to the same instance.

It would be very helpful to me if anyone could flag any potential
mistakes I may have made in this entity design since I am still
familiarizing myself with NHibernate.  We are currently evaluating NH
and the MS Entity Framework to decide which one best fits with our
model/patterns/practices/etc...  Any learning I can do without having
to make the mistake myself is incredibly beneficial.

Thanks,
Chris B

On Feb 23, 10:08 pm, Fabio Maulo <[email protected]> wrote:
> private Version latestVersion;
> public virtual Version LatestVersion {
> get{
> if(lastestVersion == null)
> {
> lastestVersion = GetLatestVersion(this.AllVersions);}
>
> return latestVersion;
>
> } }
>
> When you change something in AllVersions you should call :
> void InvalidateVersions()
> {
> lastestVersion= null;
>
> }
>
> to map it:
>
> <many-to-one name="LatestVersion" access="nosetter.camelcase"/>
>
> 2010/2/23 Chris B <[email protected]>
>
>
>
> > Fabio,
>
> > I think you are saying I could implement it like this:
>
> > public class Header
> > {
> >    public virtual int HeaderId { get; set; }
> >     public virtual Version LatestVersion { get{ return
> > GetLatestVersion(this.AllVersions); } }
> >    public virtual Version LatestApprovedVersion {  get{ return
> > GetLatestApprovedVersion(this.AllVersions); } }
> >     public virtual List<Version> AllVersions { get; set; }
> >    // other members
> > }
>
> > I had considered this kind of implementation, but the number of
> > version entities can be large and all but two (the latest and latest
> > approved) are very rarely used.  I am hoping the AllVersions
> > collection can be loaded only when viewing version history (rare), and
> > not during normal workflow operations (common).  I am assuming that
> > accessing the AllVersions collection will load all versions, even if
> > only one Version is being inquired about.  So for example,
>
> > Header h = ReadHeader();
> > Version v = h.AllVersions[4]; // lazy loads all versions into the
> > AllVersions collection, not just the one at index 4
>
> > I am also not sure where the reference to Invoice.TotalAmmount came
> > from.  My entities do not have such a field.
>
> > On Feb 23, 4:00 pm, Fabio Maulo <[email protected]> wrote:
> > > ok... then is easy
> > > You can map the two properties as access="readonly" and in its getter you
> > > can read your collection to get LastXYZ.
> > > The two properties will be saved as denormalized properties and you can
> > use
> > > it in any queries.
>
> > > If you want you can map it as access="nosetter.camelcase" and implements
> > the
> > > getter in order to read from collection when the private field is null
> > > (Note: when you change the collection adding, removing or changing a
> > member
> > > you should "reset" the LastXYZ).
>
> > > In both case what will result "denormalized" is the DB but in your model
> > > everything will be auto-protected...
> > > in practice the same you are doing with Invoice.TotalAmmount
>
> > > 2010/2/23 Chris B <[email protected]>
>
> > > > There is also a list of all previous versions in the
> > > > Header.AllVersions property. I had forgotten that I omitted it in my
> > > > original post.  The only use case where this is loaded is when a user
> > > > requests to view the version history.
>
> > > > The LatestVersion and LatestApprovedVersion references are mainly for
> > > > efficiency.  Most use cases involve either displaying/mutating the
> > > > data of the LatestVersion or reading the data of the
> > > > LatestApprovedVersion.  It would be great if we could selectively load
> > > > those two versions (on demand) without having to load all versions.
>
> > > > Here is an updated entity definition:
>
> > > > public class Header
> > > > {
> > > >    public virtual int HeaderId { get; set; }
> > > >    public virtual Version LatestVersion { get; set; }
> > > >    public virtual VersionLatestApprovedVersion { get; set; }
> > > >     public virtual List<Version> AllVersions { get; set; }
> > > >     // other members
> > > > }
>
> > > > public class Version
> > > > {
> > > >     public virtual int VersionId { get; set; }
> > > >     public virtual Header Header { get; set; }
> > > >     // other members
> > > > }
>
> > > > Does that help to clarify?
>
> > > > On Feb 23, 11:15 am, Fabio Maulo <[email protected]> wrote:
> > > > > you are showing only LatestVersion and LatestApprovedVersion
> > > > > where are previous ?
>
> > > > > 2010/2/19 Chris B <[email protected]>
>
> > > > > > Hello,
>
> > > > > > I am trying to create a mapping file for entities which look like
> > the
> > > > > > following:
>
> > > > > > public class Header
> > > > > > {
> > > > > >    public virtual int HeaderId { get; set; }
> > > > > >    public virtual Version LatestVersion { get; set; }
> > > > > >    public virtual VersionLatestApprovedVersion { get; set; }
> > > > > >    // other members
> > > > > > }
>
> > > > > > public class Version
> > > > > > {
> > > > > >     public virtual int VersionId { get; set; }
> > > > > >     public virtual Header Header { get; set; }
> > > > > >     // other members
> > > > > > }
>
> > > > > > The database looks almost exactly like this, with the obvious
> > > > > > difference being that instead of object references there are
> > foreign
> > > > > > keys for the latest/latest approved versions pointing to the
> > VersionId
> > > > > > field, and the same for the Header and HeaderId.  The table for the
> > > > > > header does allow both the latest and latest approved version ids
> > to
> > > > > > be null to allow the Header records to be inserted before the
> > Versions
> > > > > > are created.  The insert proc for the Version table takes care of
> > > > > > updating the Header.LatestVersionId to point at newly inserted
> > version
> > > > > > record.
>
> > > > > > I have thus far been unsuccessful in creating mapping files for
> > this
> > > > > > pattern, the sticking point being the LatestVersion and
> > > > > > LatestApprovedVersion properties. I'm pretty new to NHibernate, so
> > I
> > > > > > apologize if this is answered in another thread.
>
> > > > > > Any help is much appreciated. Thanks in advance.
>
> > > > > > --
> > > > > > 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]>
> > <nhusers%[email protected]<nhusers%[email protected]>
>
> > > > <nhusers%[email protected]<nhusers%[email protected]>
> > <nhusers%[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]<nhusers%[email protected]>
> > <nhusers%[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]<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