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].
>> > > To unsubscribe from this group, send email to
>> > > [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.
>> >
>> > --
>> > - Hudsonhttp://www.bestguesstheory.comhttp://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]<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]<fluent-nhibernate%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/fluent-nhibernate?hl=en.
>
--
- Hudson
http://www.bestguesstheory.com
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.