新的带有空导航属性的Poco实体,首先是EF代码

本文关键字:EF 代码 实体 Poco 导航 属性 | 更新日期: 2023-09-27 18:19:04

我首先使用实体框架代码。以下是我的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为空,
所以如果我这样写:

bp.BusinessPartnerLanguage.Add(someEntity);

我得到空异常。我设法通过改变虚拟集合属性来解决这个问题:

   private ICollection<BusinessPartnerLanguage> _BusinessPartnerLanguage;
   public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage
   {
       get { return this._BusinessPartnerLanguage ?? (this._BusinessPartnerLanguage = new HashSet<BusinessPartnerLanguage>()); }
       set { _BusinessPartnerLanguage = value; }
    }

但是我想知道为什么这不是正常的工作方式,因为它应该,有没有更好的方法来解决这个问题。

新的带有空导航属性的Poco实体,首先是EF代码

这是因为它只是一个POCO实体,如果该属性从未设置过,它将为空。

当从db上下文中检索对象时,如果启用代理,EF将创建一个代理实体。如果将属性标记为virtual,则对该虚拟属性的任何访问都将加载关系并初始化集合(如果它为null)。这和动态加载是一样的

但是如果实体在数据库中不存在(一个新实体),则不能加载关系,它必须是一个存在的实体。

如果您有现有的id,您可以以编程方式创建代理,延迟加载将加载关系并初始化集合。但是你必须使用Create方法而不是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; }
}