首先使用实体框架代码。这是我的poco课程:
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; }
}
当我在我的控制器中创建新实体时:
BusinessPartner bp = new BusinessPartner();
其导航属性 - bp.BusinessPartnerLanguage为null,
所以,如果我这样做:
bp.BusinessPartnerLanguage.Add(someEntity);
我得到null异常。我设法通过将虚拟ICollection属性更改为:
来解决此问题 private ICollection<BusinessPartnerLanguage> _BusinessPartnerLanguage;
public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage
{
get { return this._BusinessPartnerLanguage ?? (this._BusinessPartnerLanguage = new HashSet<BusinessPartnerLanguage>()); }
set { _BusinessPartnerLanguage = value; }
}
但是我想知道为什么这不应该按正常方式工作,并且有更好的方法来解决这个问题。提前谢谢。
答案 0 :(得分:1)
这是因为它只是一个POCO实体,如果从未设置过该属性,它将为null。
从db上下文中检索对象时,如果启用代理,EF将创建代理实体。如果将属性标记为虚拟属性,则对虚拟属性的任何访问都将加载关系并初始化集合(如果它为null)。渴望加载也是一样。
但如果数据库中没有实体(新实体),则无法加载关系,它必须是现有实体。
如果您有现有ID,则可以以编程方式创建代理,延迟加载将加载关系并初始化集合。但是你必须使用Create
方法而不是new运算符。
如果您创建了一个实例,则不会创建代理实例 使用new运算符的实体。 - MSDN
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
您还可以按照以下方式简化属性。
private readonly ICollection<BusinessPartnerLanguage> _BusinessPartnerLanguage
= new HashSet<BusinessPartnerLanguage>();
public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage
{
get { return _BusinessPartnerLanguage; }
}