LINQ Any()方法返回

时间:2018-05-30 15:41:06

标签: c# linq-to-entities entity-framework-core

我有一个典型的向下钻取应用程序。

这是我的应用程序的层次结构。

审核
有很多
结果

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

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

    [Display(Name = "Sensitive Designation")]
    [Column("audit_sensitive_cd")]
    public string AuditSensitiveCode { get; set; }

    [Display(Name = "Alternative Product")]
    [Column("audit_alternate_product_cd")]
    public string AuditAlternateProductCode { 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; }

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

    [Column("audit_gao_contact_tx")]
    [Display(Name = "GAO Contact:")]
    [StringLength(maximumLength: 200, ErrorMessage = "Max Length: 200")]
    public string AuditGaoContactText { get; set; }

    [Column("audit_gao_job_cd")]
    [Display(Name = "GAO Job Code:")]
    [StringLength(maximumLength: 200, ErrorMessage = "Max Length: 30")]
    public string AuditGaoJobCode { 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; }
    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_oig_manager_id")]
    [Display(Name = "OIG Audit Manager:")]
    public short? OigAuditManagerId { get; set; }
    [Display(Name = "OIG Audit Manager:")]
    [ForeignKey("OigAuditManagerId")]
    public Staff OigAuditManager { 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; }
    #endregion
}

[Table("finding")]
public class Finding
{
    private string _findingText;

    [Key]
    [Column("finding_id")]
    public int FindingId { get; set; }

    [Column("finding_audit_id")]
    public int FindingAuditId { get; set; }

    [Column("finding_cd")]
    [Display(Name = "Finding #")]
    [StringLength(15)]
    public string FindingCd { get; set; }

    [Column("finding_tx")]
    [Required(ErrorMessage = "Description Required")]
    [StringLength(7000)]
    public string FindingText
    {
        get
        {
            return _findingText;
        }
        set
        {
            _findingText = value?.Trim();
        }
    }

    [Column("finding_page_cd")]
    [StringLength(100)]
    public string FindingPageCd { get; set; }

    [Column("finding_joint_cd")]
    public string FindingJointCd { get; set; }

    [Column("finding_compliance_tx")]
    [StringLength(20)]
    public string FindingComplianceText { get; set; }

    [Column("finding_prior_year_cd")]
    [Display(Name = "Repeat Finding")]
    public string FindingPriorYearCd { get; set; }

    [Column("finding_decision_cd")]
    public string FindingDecisionCd { get; set; }

    [Column("finding_request_decision_cd")]
    public string FindingRequestDecisionCd { get; set; }

    [Column("finding_decision_ogc_concur_cd")]
    public string FindingDecisionOgcConcurCd { get; set; }

    [Column("finding_pdl_id")]
    public int? FindingPdlId { get; set; }

    [Display(Name = "Significant")]
    [Column("finding_significant_cd")]
    public string FindingSignificantCd { get; set; }

    [Column("finding_on_stay_cd")]
    public string FindingOnStayCd { get; set; }

    [Column("finding_stay_request_cd")]
    public string FindingStayRequestCd { get; set; }

    [Column("finding_last_update_dt")]
    public DateTime FindingLastUpdateDate { get; set; }

    [Column("finding_update_staff_id")]
    public short? FindingUpdateStaffId { get; set; }

    [Column("finding_cd_org")]
    public string FindingCdOrg { get; set; }

    [NotMapped]
    public string RepeatingYearsDisplayList
    {
        get
        {
            if (RepeatingYears?.Count > 0)
            {
                string repeatingYears = string.Empty;
                RepeatingYears.ForEach(ry =>
                    repeatingYears += $"{ry.FindingFyCd}, ");
                return repeatingYears.Remove(repeatingYears.Length - 2);
            }
            return string.Empty;
        }
    }

    #region Navigation Properties
    [Column("finding_finding_type_id")]
    public short? FindingTypeId { get; set; }
    [ForeignKey("FindingTypeId")]
    public FindingType FindingType { get; set; }

    [Column("finding_status_id")]
    public int? FindingStatusId { get; set; }
    [ForeignKey("FindingStatusId")]
    public Status FindingStatus { get; set; }

    public List<FindingFiscalYear> RepeatingYears { get; set; }
    public List<Recommendation> Recommendations { get; set; }

    [ForeignKey("FindingAuditId")]
    public Audit Audit { get; set; }
    #endregion
}

一个
寻找
有很多建议书。

[Table("recommend")]
public class Recommendation
{
    private string _recText;

    [Key]
    [Column("recommend_id")]
    public int RecommendationId { get; set; }

    [Column("recommend_finding_id")]
    public int RecFindingId { get; set; }

    [Column("recommend_cd")]
    public short? RecCd { get; set; }

    [StringLength(7000)]
    [Column("recommend_tx")]
    public string RecText
    {
        get
        {
            return _recText;
        }
        set
        {
            _recText = value?.Trim();
        }
    }

    [Column("recommend_contact_nm")]
    public string RecContactName { get; set; }

    [Column("recommend_status_id")]
    public int RecStatusId { get; set; }

    [Column("recommend_recommend_type_cd")]
    public short? RecTypeCd { get; set; }

    [Column("recommend_staff_id")]
    public short RecStaffId { get; set; }

    [Column("recommend_role_id")]
    public short? RecRoleId { get; set; }

    [Column("recommend_oig_decision_cd")]
    public string RecOigDecisionCd { get; set; }

    [Column("recommend_last_update_dt")]
    public DateTime RecLastUpdateDt { get; set; }

    [Column("recommend_action_determination_cd")]
    public string RecActionDeterminationCd { get; set; }

    #region Navigation Properties
    [ForeignKey("RecFindingId")]
    public Finding Finding { get; set; }

    [ForeignKey("RecTypeCd")]
    public RecommendationType RecommendationType { get; set; }

    [ForeignKey("RecStatusId")]
    public Status RecommendationStatus { get; set; }

    [ForeignKey("RecStaffId")]
    public Staff Staff { get; set; }

    public List<Assignment> Assignments { get; set; }
    #endregion

    #region NOT Mapped
    [NotMapped]
    public string RecDisplayShortDesc => $"{RecCd} {RecText}";
    #endregion
}

建议书可以有许多作业:

[Table("assignment")]
public class Assignment
{
    [Key]
    [Column("assignment_id")]
    public int AssignmentId { get; set; }

    [Column("assignment_role_id")]
    public short AssignmentRoleId { get; set; }

    [Column("assignment_type_cd")]
    public string AssignmentTypeCd { get; set; }

    [Column("assignment_dt")]
    public DateTime AssignmentDate { get; set; }

    [Column("assignment_by_staff_id")]
    public short AssignmentByStaffId { get; set; }

    [Column("assignment_recommend_id")]
    public int? AssignmentRecommendId { get; set; }

    [Column("assignment_office_id")]
    public short? AssignmentOfficeId { get; set; } 

    #region Navigation Properties
    [Column("assignment_staff_id")]
    public short AssignmentStaffId { get; set; }
    [ForeignKey("AssignmentStaffId")]
    public Staff AssignmentStaff { get; set; }

    [Column("assignment_audit_id")]
    public int? AssignmentAuditId { get; set; }
    [ForeignKey("AssignmentAuditId")]
    public Audit Audit { get; set; }

    [ForeignKey("AssignmentOfficeId")]
    public Office AssignmentOffice { get; set; }

    [ForeignKey("AssignmentRecommendId")]
    public Recommendation Recommendation { get; set; }
    #endregion
}

我有一个带有LINQ查询的View组件,使用Any()方法从顶级Audits集合一直向下来获取所有Audits,其中包含任何一个有推荐的结果,其中包含任何建议缺少角色ID为15或26的作业。如果rec中缺少其中一个或两个作业记录,那么应该将审核,审核,审核添加到审核集合中在模型中返回。

我们认为它似乎有效。但后来我们注意到,当审核中只有一个发现时,它没有被添加到集合中。只有当审计有很多调查结果并且其中一个调查结果发现缺少任务时,才会错误地添加审计。

这个foreach声明似乎对我有用:

        // Where audit has a recommendation without an assigned PO Authorizer
        //    OR without an assigned Responsible Manager (Rec Level).
        List<Audit> auditsToAssign = new List<Audit>();
        foreach (Audit audit in audits)
        {
            foreach (Finding finding in audit.Findings)
            {
                foreach (Recommendation rec in finding.Recommendations)
                {
                    if (!rec.Assignments.Any(asgn => asgn.AssignmentRoleId == 15)
                            || !rec.Assignments.Any(asgn => asgn.AssignmentRoleId == 26)
                        )
                    {
                        if (!auditsToAssign.Contains(rec.Finding.Audit))
                        {
                            auditsToAssign.Add(rec.Finding.Audit);
                        }
                    }
                }
            }
        }

但最初我试图写一个LINQ查询。 这已经过了很多次迭代,但这是目前的形式:

audits = audits.Where(a =>
            a.Findings.Count() > 0 &&
            a.Findings.Any(f =>
                f.Recommendations.Count() > 0 &&
                (
                !f.Recommendations.Any(r =>
                    r.Assignments.Any(asgn => asgn.AssignmentRoleId == 15)) ||
                !f.Recommendations.Any(r =>
                    r.Assignments.Any(asgn => asgn.AssignmentRoleId == 26))
                )
            )
        );

2 个答案:

答案 0 :(得分:2)

我并非100%确定我已按照您的说明操作,但请尝试以下操作:

        audits = audits.Where(a => 
                     a.Findings.Any(f => 
                         f.Recommendations.Any(r => 
                             !r.Assignments.Any(asgn => asgn.AssignmentRoleId == 15 || asgn.AssignmentRoleId == 26))));

此外,Linq将比你的foreach更快,因为Any()方法一旦找到匹配就会停止枚举,而你的foreach将继续枚举整个集合,即使他们在一开始就找到匹配。它也更容易阅读恕我直言(虽然你开始使用它时需要一段时间才能让你的Linq眼睛进入)。

答案 1 :(得分:0)

我认为你可以更容易地反过来(假设你有一个完整的赋值表):

var auditsToAssign = assignments.Where(asgn => asgn.AssignmentRoleId != 15 && asgn.AssignmentRoleId != 26)
                        .Select(asgn => asgn.Recommendation.Finding.Audit)
                        .Distinct();