2013-04-17 81 views
18

大多数(如果不是全部的话)我的实体框架POCO具有虚拟功能。我需要这些函数是虚拟的,以便实体可以被延迟加载。如何避免在构造函数中调用虚函数?

如果我在构造函数中初始化Accommodations那么我将在构造函数中调用虚函数,这是不好的做法。

但是如何在构造函数中初始化Accommodations

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

    public virtual ICollection<Accommodation> Accommodations { get; set; } 
} 
+1

懒加载的一点是_not_在所有初始化,直到第一次使用。 –

+0

@JohnWillemse如果我让它为空,我会在我看来得到null异常。 –

+0

不,你测试null并在需要时初始化它。请参阅下面的Willem Duncan的回答以获得使用证明。也许我们在这里混淆了不同的模式,根据丹尼尔对同样的答案的评论。 –

回答

12
public class Venue 
{ 
    private accommodations_ = new HashSet<Accommodation>(); 

    public Venue() { } 

    public virtual ICollection<Accommodation> Accommodations 
    { 
     get { return accommodations_; } 
     set { accommodations_ = value; } 
    } 
} 
+3

这是什么奇怪的命名约定?通常你会把下划线放在前面。 –

+1

@DanielHilgarth,我根本不称它为惯例 - 只是我真的需要改变的一种(可能是坏习惯)习惯;) –

+0

EF无论如何都不太喜欢领先的下划线。 – Casey

2

懒加载,你甚至不初始化Accommodations,直到它的第一次访问,所以把它null

你可以用如下使它全自动初始化本身:

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; 
    } 
} 

请务必阅读下面关于这个解决方案的评论!

+7

他正在谈论ORM上下文中的延迟加载。 ORM为您处理所有这些问题,所以您的答案忽略了这一点。此外,请参阅[这个答案](http://stackoverflow.com/questions/14774008/good-or-bad-practice-initializing-objects-in-getter/14774042#14774042)关于你在这里展示的练习。 –

+0

好点,每天学点东西,都加了一个指向答案的指针。 –

+0

感谢Daniel的链接。 –

14

另一种选择是将setter标记为私有。这将消除在构造函数中调用虚拟成员的问题。

一旦你这样做了,你需要为调用者(EF除外)提供设置时根据需要设置该属性的方法。你可以使用一个重载的构造函数来传递一个调整列表,或者可选地封装你的集合(Domain driven design)并使用方法来添加/移除项目(注意,由于EF缺乏对完全封装的支持,所以变成“hackish”收藏,不像与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; } 
} 
+2

正是我需要的。有趣的是,这个问题已经过去了一年多了,但在我去寻找它之前仅仅4个小时就发布了这个答案! – Xcelled194

0

随着C#6.0的默认初始化它可以在不使用私有变量来简化:

public class Venue 
{ 
    public virtual ICollection<Accommodation> Accommodations {get; set; } = new HashSet<Accommodation>(); 
} 
相关问题