New Poco Entity with null navigation property EF Code first
我先使用实体框架代码。以下是我的POCO课程:< BR>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class BusinessPartner { [Key] public int BusinessPartnerID { get; set; } [Required] [StringLength(255)] public string Title { get; set; } [StringLength(255)] public string Address { get; set; } public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage { get; set; } } public class Language { [Key] public int LanguageID { get; set; } [Required] [StringLength(255)] public string Title { get; set; } [Required] public bool Active { get; set; } public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage { get; set; } } public class BusinessPartnerLanguage { [Key, Column(Order = 0)] public int BusinessPartnerID { get; set; } [Key, Column(Order = 1)] public int LanguageID { get; set; } [Required] public bool Default { get; set; } public virtual BusinessPartner BusinessPartner { get; set; } public virtual Language Language { get; set; } } |
当我在控制器中创建新实体时,如:< BR>
1 |
其导航属性bp.businesspartnerlanguage为空,< BR>所以如果我做一些类似的事情:
1 | bp.BusinessPartnerLanguage.Add(someEntity); |
我得到空异常。我通过将虚拟ICollection属性更改为:
1 2 3 4 5 6 | private ICollection<BusinessPartnerLanguage> _BusinessPartnerLanguage; public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage { get { return this._BusinessPartnerLanguage ?? (this._BusinessPartnerLanguage = new HashSet<BusinessPartnerLanguage>()); } set { _BusinessPartnerLanguage = value; } } |
但我想知道为什么这个方法不能正常工作,有没有更好的方法来解决这个问题。事先谢谢。
这是因为它只是一个POCO实体,如果从未设置该属性,它将为空。
从数据库上下文检索对象时,如果启用代理,则EF将创建代理实体。如果将该属性标记为虚拟,则对该虚拟属性的任何访问都将加载关系并初始化集合(如果该集合为空)。同样的情况下,也有急切的装载。
但如果数据库中不存在实体(新实体),则无法加载关系,它必须是现有实体。
如果您有现有的ID,则可以通过编程方式创建代理,而延迟加载将加载关系并初始化集合。但是您必须使用
A proxy instance will not be created if you create an instance of an
entity using the new operator. - MSDN
1 2 3 4 5 6 7 | var context = ... int existingBPID = ... var bp = context.Set<BusinessPartner>().Create(); // BusinessPartnerLanguage = null bp.BusinessPartnerID = existingBPID; // BusinessPartnerLanguage = null context.Entry(bp).State = EntityState.Unchanged; // BusinessPartnerLanguage = null var collection = bp.BusinessPartnerLanguage; // trigger lazy loading, BusinessPartnerLanguage != null |
您还可以按照以下步骤简化属性。
1 2 3 4 5 6 | private readonly ICollection<BusinessPartnerLanguage> _BusinessPartnerLanguage = new HashSet<BusinessPartnerLanguage>(); public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage { get { return _BusinessPartnerLanguage; } } |