【问题标题】:Refactor a LINQ JOIN out of the expression从表达式中重构 LINQ JOIN
【发布时间】:2017-05-23 22:43:44
【问题描述】:

我有一个重复 3 次的 LINQ-to-SQL 表达式,只有 Join 语句发生变化。

switch (elmntType)
{
    case ElementType.Dictionary:
        auditLogs = db.st_element_audit_log.Where(al => /* some conditions */)
                      .Join(db.stt_dictionary,
                            auditLog => auditLog.element_id,
                            dictionary => dictionary.id,
                            (auditLog, dictionary) => new AuditLogAndDict { AuditLog = auditLog, Dictionary = dictionary })
                      .Where(ald => /* some conditions */)
                      .OrderByDescending(ald => /* some conditions */)
                      .Select(ald => ald.AuditLog);
        break;

    case ElementType.Concept:
        auditLogs = db.st_element_audit_log.Where(al => /* some conditions */)
                      .Join(db.stt_concept,
                            auditLog => auditLog.element_id,
                            concept => concept.id,
                            (auditLog, concept) => new {auditLog, concept})
                      .Join(db.stt_dictionary,
                            anon => anon.concept.dictionary_id,
                            dictionary => dictionary.id,
                            (anon, dictionary) => new AuditLogAndDict {AuditLog = anon.auditLog, Dictionary = dictionary})
                      .Where(ald => /* some conditions */)
                      .OrderByDescending(ald => /* some conditions */)
                      .Select(ald => ald.AuditLog);
        break;

    case ElementType.Term:
        auditLogs = db.st_element_audit_log.Where(al => /* some conditions */)
                      .Join(db.stt_term,
                            auditLog => auditLog.element_id,
                            term => term.id,
                            (auditLog, term) => new {auditLog, term})
                      .Join(db.stt_concept,
                            anon => anon.term.concept_id,
                            concept => concept.id,
                            (anon, concept) => new {anon.auditLog, concept})
                      .Join(db.stt_dictionary,
                            anon => anon.concept.dictionary_id,
                            dictionary => dictionary.id,
                            (anon, dictionary) => new AuditLogAndDict {AuditLog = anon.auditLog, Dictionary = dictionary})
                      .Where(ald => /* some conditions */)
                      .OrderByDescending(ald => /* some conditions */)
                      .Select(ald => ald.AuditLog);
        break;

    default:
        throw new ArgumentException("Unsupported ElementType enumeration.", nameof(elmntType));
}

我想知道我是否可以重构 Join 语句,只留下整个 LINQ 语句的一个实例,而 Join 来自 switch 语句:

switch (elmntType)
{
    case ElementType.Dictionary:
        // build .Join() statement
        break;

    case ElementType.Concept:
        // build .Join() statement
        break;

    case ElementType.Term:
        // build .Join() statement
        break;

    default:
        throw new ArgumentException("Unsupported ElementType enumeration.", nameof(elmntType));
}

var auditLogs = db.st_element_audit_log.Where(al => /* some conditions */)
                          // use the custom .Join() statement here
                          .Where(ald => /* some conditions */)
                          .OrderByDescending(ald => /* some conditions */)
                          .Select(ald => ald.AuditLog);

这可能吗?

【问题讨论】:

  • 右键单击 common linq 代码,然后选择 Refactor,这应该允许您提取到单个方法。如果这对您不起作用,您还可以创建 LINQ 表达式并使用字符串替换技术来更改最终查询。

标签: c# entity-framework linq linq-to-sql iqueryable


【解决方案1】:

您是否尝试过创建这样的方法:

static object MyJoin(object x)
        {
            return x.Join(db.stt_dictionary,
            auditLog => auditLog.element_id,
            dictionary => dictionary.id,
            (auditLog, dictionary) => new AuditLogAndDict { AuditLog = auditLog, Dictionary = dictionary });

        }

【讨论】:

    【解决方案2】:

    你可以像这样重构重复的代码。

    var filtered = db.st_element_audit_log.Where(al => /* some conditions */)
    IQueryable<AuditLogAndDict> joined = null;
    switch (elmntType)
    {
        case ElementType.Dictionary:
            joined = filtered.Join(db.stt_dictionary,
                auditLog => auditLog.element_id,
                dictionary => dictionary.id,
                (auditLog, dictionary) => new AuditLogAndDict { AuditLog = auditLog, Dictionary = dictionary })
            break;
    
        case ElementType.Concept:
            joined = filtered
                .Join(db.stt_concept,
                    auditLog => auditLog.element_id,
                    concept => concept.id,
                    (auditLog, concept) => new {auditLog, concept})
                .Join(db.stt_dictionary,
                    anon => anon.concept.dictionary_id,
                    dictionary => dictionary.id,
                    (anon, dictionary) => new AuditLogAndDict {AuditLog = anon.auditLog, Dictionary = dictionary})
            break;
    
        case ElementType.Term:
            joined = filtered
                .Join(db.stt_term,
                    auditLog => auditLog.element_id,
                    term => term.id,
                    (auditLog, term) => new {auditLog, term})
                .Join(db.stt_concept,
                    anon => anon.term.concept_id,
                    concept => concept.id,
                    (anon, concept) => new {anon.auditLog, concept})
                .Join(db.stt_dictionary,
                    anon => anon.concept.dictionary_id,
                    dictionary => dictionary.id,
                    (anon, dictionary) => new AuditLogAndDict {AuditLog = anon.auditLog, Dictionary = dictionary})
            break;
    
        default:
            throw new ArgumentException("Unsupported ElementType enumeration.", nameof(elmntType));
    }
    
    auditLogs = joined
        .Where(ald => /* some conditions */)
        .OrderByDescending(ald => /* some conditions */)
        .Select(ald => ald.AuditLog);
    

    【讨论】:

    • 是的,就可以了。谢谢@juharr。我想它不可能被重构为一个方法/变量,而不是放在 in-between IQueryable 构造? (如果不清楚,请忽略它。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    相关资源
    最近更新 更多