简体   繁体   中英

New Poco Entity with null navigation property EF Code first

im using entity framework code first. Here are my poco classes:

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

when i create new entity in my controller like:

BusinessPartner bp = new BusinessPartner();

its navigation property - bp.BusinessPartnerLanguage is null,
so if i do something like :

bp.BusinessPartnerLanguage.Add(someEntity);

im getting null exception. I managed to work around this by changing virtual ICollection properties to :

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

But i wanna know why isnt this working in normal way as it should, and is there a better way to work around this problem. Thanks in advance.

It's because It is just a POCO entity, if the property never been set, it will be null.

When retrieving an object from db context, if you enable the proxy, EF will create a proxy entity. And if you mark the property as virtual, any access to the virtual property will load the relationship and initialize the collection (if it's null). And it's the same thing with eager loading.

But you can't load the relationship if the entity doesn't exist in the database (a new one), it has to be an existing entity.

If you have existing id, you can create the proxy programmatically and lazy loading will load the relationship and initialize the collection. But you have to use Create method instead of new operator.

A proxy instance will not be created if you create an instance of an entity using the new operator. - 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

And you can also simplify the property as follow.

private readonly ICollection<BusinessPartnerLanguage> _BusinessPartnerLanguage
    = new HashSet<BusinessPartnerLanguage>();
public virtual ICollection<BusinessPartnerLanguage> BusinessPartnerLanguage
{
    get { return _BusinessPartnerLanguage; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM