19

Most (if not all) my Entity Framework POCOs have virtual functions. I need these functions to be virtual so that the entities can be lazy-loaded.

If I initialize Accommodations in constructor then I will be calling a virtual function in constructor, which is bad practice.

But how can I initialize Accommodations if not in the constructor?

public class Venue
{
    public Venue()
    {
        Accommodations = new HashSet<Accommodation>();
    }

    public virtual ICollection<Accommodation> Accommodations { get; set; }
}
Rosdi Kasim
  • 24,267
  • 23
  • 130
  • 154
  • 1
    The point of lazy loading is _not_ to initialize it at all, until first use. – John Willemse Apr 17 '13 at 08:48
  • @JohnWillemse If I let it null I will get null exception in my view. – Rosdi Kasim Apr 17 '13 at 09:04
  • No, you test for null and initialize it when needed. See Willem Duncan's answer below for a demonstration of the use. Maybe we're confusing different patterns here, as per Daniel's comment on the same answer. – John Willemse Apr 17 '13 at 09:08

4 Answers4

15

Another option is to mark the setter as private. This will do away with the issue of calling virtual members in constructor.

Once you do that, you need to provide ways for callers (other than EF) to set that property as needed by your design. You can use an overloaded constructor to pass in a list of accommodations, or optionally encapsulate your collection (Domain driven design) and use methods to add/remove items (note, with EF this becomes "hackish", as it lacks support for fully encapsulated collections, unlike with NHibernate):

public class Venue
{
    public Venue()
    {
        Accommodations = new HashSet<Accommodation>();
    }

    public Venue(ICollection<Accommodation> accommodations)
    {
        Accommodations = new List<Accommodation>(accommodations);
    }

    public virtual ICollection<Accommodation> Accommodations { get; private set; }
}
Thiago Silva
  • 14,183
  • 3
  • 36
  • 46
  • 2
    Exactly what I needed. Funny how this question is over a year old, and yet you post this answer a mere 4 hours before I go looking for it! – Xcelled May 28 '14 at 20:28
13
public class Venue
{
    private accommodations_ = new HashSet<Accommodation>();

    public Venue()  { }

    public virtual ICollection<Accommodation> Accommodations 
    {
        get { return accommodations_; }
        set { accommodations_ = value; }
    }
}
Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
4

With the C# 6.0 default initialization it could be simplified without use of private variables:

public class Venue
{
    public virtual ICollection<Accommodation> Accommodations {get; set; } = new HashSet<Accommodation>();
}
nshathish
  • 417
  • 8
  • 23
2

With lazy loading, you do not even initialize the Accommodations untill it's first accessed, so leave it null.

You can wrap as follows to make it automaticly initialize itself:

private ICollection<Accommodation> _accommodations;

public virtual ICollection<Accommodation> Accommodations { 
    get { 
        if (_accommodations == null)
        {
             // Initialize or load data here.
             _accommodations = new HashSet<Accommodation>();
        }
        return _accomodations;
    } 
    set {
        _accommodations = value;
    } 
}

Be sure to read the comment below regarding this solution!

w5l
  • 5,341
  • 1
  • 25
  • 43
  • 7
    He is talking about lazy loading in the context of an ORM. The ORM takes care of all this for you, so your answer misses the point. Additionally, please see [this answer](http://stackoverflow.com/questions/14774008/good-or-bad-practice-initializing-objects-in-getter/14774042#14774042) regarding the practice you show here. – Daniel Hilgarth Apr 17 '13 at 09:06
  • Good point, learn something every day, have added a pointer to the answer. – w5l Apr 17 '13 at 09:43
  • Thanks for the link Daniel. – Rosdi Kasim Apr 17 '13 at 12:05