如果您要包含的属性为null,则在Entity Framework Core 2.0中调用Include将使该实体为null

时间:2018-09-13 22:54:23

标签: entity-framework-core

我正在获得这样的EF核心实体:

Audit audit = _auditRepo.Audits
            .Include(a => a.Status)
            .Include(a => a.AuditType)
            .Include(a => a.Office)
            .Include(a => a.LeadOffice)
            .Include(a => a.External)
            .Include(a => a.External).ThenInclude(e => e.AuditResult)
            .Include(a => a.External).ThenInclude(e => e.PreparerType)
            .Include(a => a.External).ThenInclude(e => e.Auditee)
            .Where(a => a.AuditID == id)
            .FirstOrDefault();

我的审核返回空值,因为它没有办公室。如果我有办公室,则会进行审核。

如果我没有办公室,但我将其注释掉:

.Include(a => a.Office) 

审核也重新填充。

这是我的审核单位:

[Table("audit")]
public class Audit
{
    private string _auditAcnCd;
    private string _title;
    private string _summary;

    [Key]
    [Column("audit_id")]
    public int AuditID { get; set; }

    [Required(ErrorMessage = "ACN Required")]
    [Display(Name="ACN:")]
    [Column("audit_acn_cd")]
    public string AuditAcnCd
    {
        get
        {
            return _auditAcnCd;
        }
        set
        {
            _auditAcnCd = value?.Trim();
        }
    }

    [Required(ErrorMessage = "Title Required")]
    [Display(Name = "Title:")]
    [Column("audit_report_title_tx")]
    public string Title
    {
        get
        {
            return _title;
        }
        set
        {
            _title = value?.Trim();
        }
    }

    [StringLength(maximumLength: 1000, ErrorMessage = "Max Length: 1000")]
    [Display(Name = "Summary:")]
    [Column("audit_summary_tx")]
    public string Summary
    {
        get
        {
            return _summary;
        }
        set
        {
            _summary = value?.Trim();
        }
    }

    [Required(ErrorMessage = "Issuer Required")]
    [Display(Name="Issuer:")]
    [Column("audit_issuer_tx")]
    public string Issuer { get; set; }

    [RegularExpression("([1-9][0-9]*)", ErrorMessage = "Priority must be a number.")]
    [Display(Name = "Priority:")]
    [Column("audit_priority_cd")]
    public short? Priority { get; set; }

    [Display(Name = "Lead Office:")]
    [Column("audit_lead_office_id")]
    public short? LeadOfficeID { get; set; }

    #region Navigation Properties
    [Required(ErrorMessage = "Audit Type Required.")]
    [Display(Name = "Audit Type:")]
    [Column("audit_audit_type_id")]
    public short AuditTypeID { get; set; }
    [Display(Name = "Audit Type:")]
    public AuditType AuditType { get; set; }

    [Column("audit_status_id")]
    public int StatusID { get; set; } 
    public Status Status { get; set; }

    [Required(ErrorMessage = "Office is Required.")]
    [Display(Name = "Offices:")]
    [Column("audit_office_id")]
    public short? OfficeID { get; set; }
    // [ForeignKey("OfficeID")]
    public Office Office { get; set; }

    [ForeignKey("AuditID")]
    public External External { get; set; }

    public IEnumerable<AuditLog> AuditLogs { get; set; }
    public IEnumerable<Finding> Findings { get; set; }
    public IEnumerable<Assignment> Assignments { get; set; }

    [Column("audit_update_staff_id")]
    public short UpdateStaffID { get; set; }

    [Column("audit_fsa_office_id")]
    [Display(Name = "FSA Audit Lead:")]
    public int? FsaLeadOfficeId { get; set; }
    [Display(Name = "FSA Audit Lead:")]
    [ForeignKey("FsaLeadOfficeId")]
    public FSAOffice FsaLeadOffice { get; set; }

    [ForeignKey("LeadOfficeID")]
    public Office LeadOffice { get; set; }
}

这是我的Office实体:

[Table("office")]
public class Office
{
    private string _OfficeCd;
    private string _OfficeNm;
    private string _OfficeOrganizationCd;

        [Key]
    [Column("office_id")]
    public short OfficeID { get; set; }

    [Required(ErrorMessage = "Numeric Code is required")]
    [StringLength(2, ErrorMessage = "Max Length is two")]
    [Display(Name = "Office Numeric Code:")]
    [Column("office_cd")]
    public string OfficeCd
    {
        get
        {
            return _OfficeCd;
        }
        set
        {
            _OfficeCd = value?.Trim();
        }
    }
    [Required(ErrorMessage = "Office Name is required")]
    [Display(Name = "Office Name:")]
    [Column("office_nm")]
    public string OfficeNm
    {
        get
        {
            return _OfficeNm;
        }
        set
        {
            _OfficeNm = value?.Trim();
        }
    }


    [Required(ErrorMessage = "Office Abbreviation is required")]
    [Display(Name = "Office Abbreviation:")]
    [Column("office_organization_cd")]
    public string OfficeOrganizationCd
    {
        get
        {
            return _OfficeOrganizationCd;
        }
        set
        {
            _OfficeOrganizationCd = value?.Trim();
        }
    }


    [Display(Name = "Status:")]
    [Column("office_active_cd")]
    public string OfficeActiveCd { get; set; }

    [Display(Name = "Parent Office:")]
    [Column("office_parent_id")]
    public short? OfficeParentId { get; set; }
    [Display(Name = "Parent Office:")] 
    [ForeignKey("OfficeParentId")]
    public Office ParentOffice { get; set; }

    public List<StaffOffice> StaffOffices { get; set; }
}

我所有其他属性都正常。我是否需要在onModelCreating中进行配置?

1 个答案:

答案 0 :(得分:2)

解释很简单-您的实体模型和数据库之间存在差异。

当FK像您的OfficeId一样可为空时,该关系是可选的,EF Core希望该列可以为空,并在检索相关数据时使用 left external join (通过Include

但是在某些时候,您似乎向FK属性添加了[Required]属性:

[Required(ErrorMessage = "Office is Required.")] // <-- the problem
[Display(Name = "Offices:")]
[Column("audit_office_id")]
public short? OfficeID { get; set; }
// [ForeignKey("OfficeID")]
public Office Office { get; set; }

请注意[[Required]属性和IsRequired()流利的API优先于数据类型(当然,您不能使非可空类型成为可空类型,但可以采用其他方法)。结果是,现在EF认为OfficeID FK是必需的(即数据库中不可为空的列)并执行内部联接,这当然会过滤如果记录包含空FK值,则返回结果。

解决方案是删除该属性。通常,始终保持模型和数据库同步。每当您更改模型中的某些内容时,请添加新的迁移。如果它是空的,请将其删除,否则请根据模型元数据/配置查看EF假定的数据库更改。