Yeah we don't have support for lazy=extra yet. You could say that I have my lazy attribute set to extra - I want someone else to submit the patch!
On Tue, Feb 2, 2010 at 3:39 PM, Robert Eberhart <[email protected]>wrote: > I'm intrigued about lazy=extra but tried to research it and couldn't find > any information. If I'm correct, HasMany, HasManyToMany, etc. don't have > SetAttribute like earlier versions of FNH. Do you have any links you could > point me to? > > > On Feb 1, 2010, at 8:17 PM, Hudson Akridge <[email protected]> > wrote: > > Your thoughts on why to just expose it out as an ienumerable make sense. > There's positives and negatives to both. Wrapping it in a ReadOnlyCollection > initializes it, as well as prevents you from ever being able to take > advantage of lazy=extra. > > On Mon, Feb 1, 2010 at 6:37 PM, Paul Batum < <[email protected]> > [email protected]> wrote: > >> Yes, sorry, there was an error in my code. You can map the member as >> either a field or a property, but you have to use the appropriate >> access mechanism. ReadOnlyPropertyThroughCamelCaseField tells >> NHibernate to use the mapped property when getting the value, and to >> look for a field with camel case naming and to use that when setting >> the value. If the underlying member is an autoproperty, then it will >> fail to find a matching field. >> >> >> On Tue, Feb 2, 2010 at 8:17 AM, TheNephalim < <[email protected]> >> [email protected]> wrote: >> > >> > I implemented what Paul suggested, although I had to do it slightly >> > differently and I'm not sure why. >> > >> > public class User { >> > >> > private IList<Phone> _phones; >> > >> > /// <summary> >> > /// A list of contact phone numbers. >> > /// </summary> >> > public virtual IEnumerable<Phone> Phones { >> > get { return _phones; } >> > } >> > >> > public virtual void AddPhone(Phone phone) { >> > Check.Require(phone != null, "Phone cannot be left >> > undefined."); >> > >> > if (!_phones.Contains(phone)) { >> > _phones.Add(phone); >> > } >> > } >> > } >> > >> > The mapping for the property is: >> > >> > HasMany<Phone>(x => x.Phones) >> > .Access.ReadOnlyPropertyThroughCamelCaseField >> > (Prefix.Underscore) >> > .Table("Phone") >> > .KeyColumn("UserId") >> > .Cascade.All().Inverse() >> > .AsBag(); >> > >> > If I added the get/set to the private IList<Phone> _phones, I received >> > an error indicating that it couldn't find the field "_phones". >> > However, now that I'm thinking about it, that might make sense because >> > having the get/set would indicate a propert and not a field. I'm not >> > sure if the the Property access strategy would work and I believe that >> > you would also have to use the Reveal.Property<Entity>("Property") >> > method. I also think that you would probably have to rename the >> > property to something like m_Phones. I have not have too much luck >> > using the Reveal.Property method; sometimes it seems to work and other >> > times....not. >> > >> > I also had to change the List<T> to IList<T>, otherwise to access >> > contains I would have to access it through the public IEnumerable >> > Phones instead of the private variable. To add a new value, I would >> > need to access the private variable, but would receive an error >> > indicating an index out of range exception. Changing the collection >> > from List<T> to IList<T> seems to have remedied that problem. >> > >> > I'm going to continue testing to make sure that everything is cool. >> > It appears, though, that I have reached something that I can >> > definitely live with. >> > >> > Thanks again, >> > Robert >> > >> > On Jan 30, 6:53 pm, Paul Batum <[email protected]> wrote: >> > > I'm familiar with what AsReadOnly does - it used to be my preferred >> > > approach! Until I realised that compile time errors are preferable to >> > > runtime errors :) >> > > >> > > You could argue that a combination of both techniques is best - that >> way >> > > you're still exposing a readonly interface and preventing the casting >> > > problem. But if my developers are casting back to lists instead of >> using the >> > > appropriate methods (AddXXX, RemoveXXX), I've got bigger problems. I >> try to >> > > expose a public interface that makes the wrong things hard and the >> right >> > > things easy - I rarely go further than that. YMMV. >> > > >> > > On Sun, Jan 31, 2010 at 2:27 AM, Hudson Akridge < >> [email protected]>wrote: >> > > >> > > > You can make the getter an IEnumerable for your property wrapper, >> but you >> > > > can still cast it back to a list and then make modifications to it. >> > > > .AsReadOnly() wraps it in a new read only collection that throws >> exceptions >> > > > whenever .Add/.Remove or any other collection modification methods >> are >> > > > attempted to be called. Otherwise all you're doing it providing a >> read only >> > > > interface, but not actually enforcing it. >> > > >> > > > Example: >> > > > public class Person >> > > > { >> > > > public Person() >> > > > { >> > > > _test = new List<string>(); >> > > > } >> > > > private readonly IList<string> _test; >> > > > public IEnumerable<string> Test >> > > > { >> > > > get { return _test; } >> > > > } >> > > > } >> > > >> > > > //Usage >> > > > var tmp = new Person(); >> > > > var tmp2 = tmp.Test as List<string>; >> > > > tmp2.Add("test"); >> > > >> > > > tmp2 will have a count of 1 after this, and "test" will have been >> added. >> > > > This is typically not what you'd want a user of your model to be >> able to do. >> > > >> > > > On Fri, Jan 29, 2010 at 11:23 PM, Paul Batum <[email protected]> >> wrote: >> > > >> > > >> Not sure if I'm following entirely, but my approach to exposing >> > > >> collections is to make the getter an IEnumerable: >> > > >> > > >> public class Foo >> > > >> { >> > > >> private List<Bar> _bars { get; set; } >> > > >> > > >> public IEnumerable<Bar> Bars >> > > >> { >> > > >> get { return _bars; } >> > > >> } >> > > >> } >> > > >> > > >> Then I map this using an access strategy: >> > > >> > > >> public void Override(AutoMapping<Foo> mapping) >> > > >> { >> > > >> mapping.HasMany(x => x.Bars) >> > > >> > > >> .Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore) >> > > >> } >> > > >> > > >> On Sat, Jan 30, 2010 at 4:20 AM, TheNephalim < >> [email protected]>wrote: >> > > >> > > >>> I'm definitely going to look into the other strategies that you >> > > >>> mentioned. >> > > >> > > >>> One that I found, and seems to work, is the wrapper strategy that >> you >> > > >>> alluded to in item number 4. I created a private property that is >> > > >>> revealed in the mapping and is accessed using the wrapper in a >> public >> > > >>> property. When I tested two other properties that I had >> implemented >> > > >>> in this fashion, NHibernate determined that the collections were >> not >> > > >>> initialized using the assert that I mentioned in my previous >> posting >> > > >>> and only generated SQL if I directly accessed the collection >> directly, >> > > >>> i.e. User.Phones.Count. >> > > >> > > >>> Thank you for your response and confirming what I was thinking as >> well >> > > >>> as giving me some other avenues to pursue. >> > > >> > > >>> -Robert Eberhart >> > > >> > > >>> On Jan 29, 11:54 am, Hudson Akridge <[email protected]> >> wrote: >> > > >>> > You may want to toss your question over to the NHUsers google >> group, >> > > >>> but >> > > >>> > I'll give you my feedback for as much as It'll help ;) >> > > >> > > >>> > is this a trade off wherein we sacrifice encapsulation for >> performance >> > > >> > > >>> > This. As far as I'm able to gleen, that is the correct >> assumption to >> > > >>> make. >> > > >>> > There are ways around this. >> > > >>> > 1.) Don't access the collection unless you absolutely need it >> > > >>> > 2.) Look into doing Join Fetch's during your queries when you >> get the >> > > >>> data >> > > >>> > back if you know you're going to be using that collection as a >> result >> > > >>> of the >> > > >>> > query. >> > > >>> > 3.) Look into batch or subselect fetching, this is a good >> loading >> > > >>> strategy >> > > >>> > imo >> > > >>> > 4.) Look into lazy=extra. This allows you to do counts, >> contains, and a >> > > >>> few >> > > >>> > other common collection statements without loading the >> collection. You >> > > >>> will >> > > >>> > still have to access the backing collection, but you can write a >> > > >>> wrapper in >> > > >>> > your model. For example: >> > > >>> > public virtual int FastCountOfLogins() >> > > >>> > { >> > > >>> > return _logins.Count(); >> > > >> > > >>> > } >> > > >> > > >>> > That will keep your collection lazy loaded until you actually >> need to >> > > >>> do >> > > >>> > something like a for each and iterate over it. >> > > >>> > 5.) Grab nhprofiler. This is one of the single best tools for >> finding >> > > >>> bottle >> > > >>> > necks in your application. >> > > >> > > >>> > On Fri, Jan 29, 2010 at 8:10 AM, TheNephalim < >> > > >>> [email protected]>wrote: >> > > >> > > >>> > > I have several issues that I'm working on, because I'm a >> newbie at >> > > >>> > > this, and wanted to address the one that I "solved" first. >> > > >> > > >>> > > The problem was that I was noticing that all of my collections >> were >> > > >>> > > not loading lazily, no matter what I did to mark them as such. >> It >> > > >>> > > then dawned on me that the problem was the way I was returning >> the >> > > >>> > > collection. >> > > >> > > >>> > > For example, >> > > >> > > >>> > > public virtual IList<Login> Logins { >> > > >>> > > get { return new List<Login>(_logins).AsReadOnly(); >> } >> > > >>> > > protected set { _logins = value; } >> > > >>> > > } >> > > >> > > >>> > > I did it this way because if you just return _logins, you're >> actually >> > > >>> > > returning a reference to the private variable which violates >> > > >>> > > encapsulation and the whole reason for marking it private in >> the >> > > >>> first >> > > >>> > > place. >> > > >> > > >>> > > The problem is that the parent object, User, is a proxy. Any >> time >> > > >>> > > that that parent object was accessed, for example, to set >> > > >>> > > User.LastName, a query for each of the collections was fired. >> The >> > > >>> > > solution was to change the property to this: >> > > >> > > >>> > > public virtual IList<Login> Logins { >> > > >>> > > get { return _logins; } >> > > >>> > > protected set { _logins = value; } >> > > >>> > > } >> > > >> > > >>> > > I have run several tests in NUnit and watched the queries >> coming back >> > > >>> > > to know that this is what's happening. Additionally, I used >> the >> > > >>> > > following: >> > > >> > > >>> > > >> Assert.IsFalse(NHibernateUtil.IsInitialized(testUser.Logins)); >> > > >> > > >>> > > It passes for the second property implementation and not the >> first. >> > > >> > > >>> > > The question I have is this: Is there a way to encapsulate >> the >> > > >>> > > private variable but still have a proxy for lazy loading, or >> is this >> > > >>> a >> > > >>> > > trade off wherein we sacrifice encapsulation for performance? >> > > >> > > >>> > > Any help you can offer is appreciated. >> > > >> > > >>> > > Sincerely, >> > > >>> > > Robert Eberhart >> > > >> > > >>> > > -- >> > > >>> > > You received this message because you are subscribed to the >> Google >> > > >>> Groups >> > > >>> > > "Fluent NHibernate" group. >> > > >>> > > To post to this group, send email to >> > > >>> <[email protected]> >> [email protected]. >> > > >>> > > To unsubscribe from this group, send email to >> > > >>> > > <fluent-nhibernate%[email protected]> >> [email protected]< >> fluent-nhibernate%[email protected]<fluent-nhibernate%[email protected]> >> > >> > > >>> <fluent-nhibernate%[email protected]<fluent-nhibernate%[email protected]> >> <fluent-nhibernate%[email protected]<fluent-nhibernate%[email protected]> >> > >> > > >> > > >>> > > . >> > > >>> > > For more options, visit this group at >> > > >>> > > <http://groups.google.com/group/fluent-nhibernate?hl=en> >> http://groups.google.com/group/fluent-nhibernate?hl=en. >> > > >> > > >>> > -- >> > > >>> > - >> > > >>> > Hudsonhttp://www.bestguesstheory.comhttp://<http://twitter.com/HudsonAkridge> >> twitter.com/HudsonAkridge >> > > >> > > >>> -- >> > > >>> You received this message because you are subscribed to the Google >> Groups >> > > >>> "Fluent NHibernate" group. >> > > >>> To post to this group, send email to >> <[email protected]>[email protected]. >> > > >>> To unsubscribe from this group, send email to >> > > >>> <fluent-nhibernate%[email protected]> >> [email protected]< >> fluent-nhibernate%[email protected]<fluent-nhibernate%[email protected]> >> > >> > > >>> . >> > > >>> For more options, visit this group at >> > > >>> <http://groups.google.com/group/fluent-nhibernate?hl=en> >> http://groups.google.com/group/fluent-nhibernate?hl=en. >> > > >> > > >> -- >> > > >> You received this message because you are subscribed to the Google >> Groups >> > > >> "Fluent NHibernate" group. >> > > >> To post to this group, send email to >> <[email protected]>[email protected]. >> > > >> To unsubscribe from this group, send email to >> > > >> <fluent-nhibernate%[email protected]> >> [email protected]< >> fluent-nhibernate%[email protected]<fluent-nhibernate%[email protected]> >> > >> > > >> . >> > > >> For more options, visit this group at >> > > >> <http://groups.google.com/group/fluent-nhibernate?hl=en> >> http://groups.google.com/group/fluent-nhibernate?hl=en. >> > > >> > > > -- >> > > > - Hudson >> > > > <http://www.bestguesstheory.com>http://www.bestguesstheory.com >> > > > <http://twitter.com/HudsonAkridge>http://twitter.com/HudsonAkridge >> > > >> > > > -- >> > > > You received this message because you are subscribed to the Google >> Groups >> > > > "Fluent NHibernate" group. >> > > > To post to this group, send email to >> <[email protected]>[email protected]. >> > > > To unsubscribe from this group, send email to >> > > > <fluent-nhibernate%[email protected]> >> [email protected]< >> fluent-nhibernate%[email protected]<fluent-nhibernate%[email protected]> >> > >> > > > . >> > > > For more options, visit this group at >> > > > <http://groups.google.com/group/fluent-nhibernate?hl=en> >> http://groups.google.com/group/fluent-nhibernate?hl=en. >> > >> > -- >> > You received this message because you are subscribed to the Google >> Groups "Fluent NHibernate" group. >> > To post to this group, send email to >> <[email protected]>[email protected]. >> > To unsubscribe from this group, send email to >> <fluent-nhibernate%[email protected]> >> [email protected]. >> > For more options, visit this group at >> <http://groups.google.com/group/fluent-nhibernate?hl=en> >> http://groups.google.com/group/fluent-nhibernate?hl=en. >> > >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Fluent NHibernate" group. >> To post to this group, send email to <[email protected]> >> [email protected]. >> To unsubscribe from this group, send email to >> <fluent-nhibernate%[email protected]> >> [email protected]. >> For more options, visit this group at >> <http://groups.google.com/group/fluent-nhibernate?hl=en> >> http://groups.google.com/group/fluent-nhibernate?hl=en. >> >> > > > -- > - Hudson > <http://www.bestguesstheory.com>http://www.bestguesstheory.com > <http://twitter.com/HudsonAkridge>http://twitter.com/HudsonAkridge > > -- > You received this message because you are subscribed to the Google Groups > "Fluent NHibernate" 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/fluent-nhibernate?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "Fluent NHibernate" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]<fluent-nhibernate%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/fluent-nhibernate?hl=en. > -- You received this message because you are subscribed to the Google Groups "Fluent NHibernate" 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/fluent-nhibernate?hl=en.
