2016-09-30 87 views
1

我在这里有此代码。我认为这不是很有效率,我想知道是否有某种方式可以让我这样做。因此,某些条款在开始或结束时添加,而不是重复三次。我将不胜感激,如果任何人都可以给我任何意见和展示我如何能做到这一点:有没有办法推迟LINQ语句中的.WHER子句?

 List<Phrase> phrases; 

     switch (options.PhraseTypeSelectId) 
     { 
      case 0: 
       phrases = await db.Phrases 
       .Where(w => ((w.CategoryId == options.CategorySelectId || options.CategorySelectId == null) || 
          (w.ChapterId == options.ChapterSelectId || options.ChapterSelectId == null))) 
       .Where(w => (w.EnglishAscii >= es1 && w.EnglishAscii <= ee1) || (w.EnglishAscii >= es2 && w.EnglishAscii <= ee2)) 
       .Where(w => (w.RomajiAscii >= rs1 && w.RomajiAscii <= re1) || (w.RomajiAscii >= rs2 && w.RomajiAscii <= ee2)) 
       .Where(w => (options.CreatedBy == 0 || w.CreatedBy == options.CreatedBy)) 
       .Where(w => (options.ModifiedBy == 0 || w.ModifiedBy == options.ModifiedBy)) 
       .Where(w => (options.JLPT == 0 || w.JLPT == options.JLPT)) 
       .AsNoTracking() 
       .ToListAsync(); 
       return Ok(phrases); 
      case 1: 
       phrases = await db.Phrases 
       .Where(w => ((w.CategoryId == options.CategorySelectId || options.CategorySelectId == null))) 
       .Where(w => (w.EnglishAscii >= es1 && w.EnglishAscii <= ee1) || (w.EnglishAscii >= es2 && w.EnglishAscii <= ee2)) 
       .Where(w => (w.RomajiAscii >= rs1 && w.RomajiAscii <= re1) || (w.RomajiAscii >= rs2 && w.RomajiAscii <= ee2)) 
       .Where(w => (options.CreatedBy == 0 || w.CreatedBy == options.CreatedBy)) 
       .Where(w => (options.ModifiedBy == 0 || w.ModifiedBy == options.ModifiedBy)) 
       .Where(w => (options.JLPT == 0 || w.JLPT == options.JLPT)) 
       .AsNoTracking() 
       .ToListAsync(); 
       return Ok(phrases); 
      case 2: 
       phrases = await db.Phrases 
       .Where(w => ((w.ChapterId == options.ChapterSelectId || options.ChapterSelectId == null))) 
       .Where(w => (w.EnglishAscii >= es1 && w.EnglishAscii <= ee1) || (w.EnglishAscii >= es2 && w.EnglishAscii <= ee2)) 
       .Where(w => (w.RomajiAscii >= rs1 && w.RomajiAscii <= re1) || (w.RomajiAscii >= rs2 && w.RomajiAscii <= ee2)) 
       .Where(w => (options.CreatedBy == 0 || w.CreatedBy == options.CreatedBy)) 
       .Where(w => (options.ModifiedBy == 0 || w.ModifiedBy == options.ModifiedBy)) 
       .Where(w => (options.JLPT == 0 || w.JLPT == options.JLPT)) 
       .AsNoTracking() 
       .ToListAsync(); 
       return Ok(phrases); 
     } 
     return BadRequest(); 

我想包括switch语句,因为我没有试过这个,它变得非常混乱与相关的。凡条款短语类型选择ID

+2

我不能见案例1和2 – HimBromBeere

+1

之间的差异为什么不创建一个包含了常用的逻辑方法您的案件,并在案件本身添加案件的具体逻辑? –

+0

您可以在'select'子句之外进行赋值'phrase = await db.Phrases'。在'select cases'中,你可以连接'where'这样的表达式,如'phrases = phrases.where()' – hellowstone

回答

3

由于我无法编译该示例,因此我不能100%确定它会编译,但您应该掌握它的要点。

您可以为不同的PhraseTypeSelecteId创建特定表达式,并在稍后使用.Where()方法。

Expression<Func<Phrase, bool>> phraseTypePredicate = null; 

switch (options.PhraseTypeSelectId) 
{ 
    case 0: 
     phraseTypePredicate = 
      w => ((w.CategoryId == options.CategorySelectId || options.CategorySelectId == null) || 
        (w.ChapterId == options.ChapterSelectId || options.ChapterSelectId == null)); 
     break; 
    case 1: 
     phraseTypePredicate = 
      w => ((w.CategoryId == options.CategorySelectId || options.CategorySelectId == null)); 
     break; 
    case 2: 
     phraseTypePredicate = 
      w => ((w.ChapterId == options.ChapterSelectId || options.ChapterSelectId == null)); 
     break; 
} 

if (phraseTypePredicate != null) 
{ 
    List<Phrase> phrases = phrases = await db.Phrases 
     .Where(phraseTypePredicate) 
     .Where(w => (w.EnglishAscii >= es1 && w.EnglishAscii <= ee1) || (w.EnglishAscii >= es2 && w.EnglishAscii <= ee2)) 
     .Where(w => (w.RomajiAscii >= rs1 && w.RomajiAscii <= re1) || (w.RomajiAscii >= rs2 && w.RomajiAscii <= ee2)) 
     .Where(w => (options.CreatedBy == 0 || w.CreatedBy == options.CreatedBy)) 
     .Where(w => (options.ModifiedBy == 0 || w.ModifiedBy == options.ModifiedBy)) 
     .Where(w => (options.JLPT == 0 || w.JLPT == options.JLPT)) 
     .AsNoTracking() 
     .ToListAsync(); 
    return Ok(phrases); 
} 

return BadRequest(); 
+0

你可以直接将'Expression Tree'提供给'Where'子句,还是需要编译成'Func ' 。您不编译表达式树。 –

+2

@MrinalKamboj因为这是一个'IQueryable',我们想保留它作为'Expression'来允许EntityFramework执行过滤服务器端。如果它是'Func',它将使用该方法的IEnumerable版本,并将导致应用程序加载所有行并执行过滤客户端(旁边:'AsNoTracking'和'ToListAsync'不起作用无论如何,如果我们使用'Where'的IEnumerable版本)。 – Howwie

+0

好吧,谢谢,看起来像这些调用'AsNoTracking()'和'ToListAsync()'给了你一个关于'IQueryable'的想法,否则它在任何地方都没有提到 –

3

你可以使用扩展方法.AsQueryable()这将返回一个LINQ statment的前半部分为可查询的表达,从而进一步操纵和变压器如果需要的话。

例如

var query =db.Phrases.where(phraseTypePredicate).AsQueryable(); 

switch(options.PhraseTypeSelectId) 
{ 
    case 1: 
    query = query.where(case1Predicate); 
    break; 
    case 2: 
    query = query.where(case2Predicate); 
    break; 
    ... 
} 

var results = query.ToList(); // or someother way of enumerating the expression 
1

LINQ查询上的IQueryableIEnumerable不被评估,直到你真正循环的结果 - 通过遍历它,或致电ToList()或诸如此类。

因此,您可以分阶段建立的东西,例如:

var exp = dbcontext.Logs.Where(x => x.Code == 4); 

,不会在数据库上执行任何代码呢。然后你就可以在以后说:

var logs = await exp.Where(x => x.Module == "AUTH").ToListAsync(); 

执行,因为ToListAsync()的查询。

这样做的一个巨大优势是能够用合理的方法分阶段构建查询(而不是切分周围的SQL字符串),并且相信Entity Framework或您正在使用的任何LINQ提供程序将使其变为合理查询(大部分时间都是这样)。

因此,对于你庞大的例子,我不会试图在这里改写它,但你肯定可以做一些事情以这种形式:

var query = await db.Phrases; 
// common where clauses 

switch (options.PhraseTypeSelectId) { 
    case 0: 
     query = query.Where(w => /* appropriate restriction for 0 */); 
     break; 
    // other cases 
} 

// more conditional where clauses perhaps 

// projection clauses like Select() 

// finally, execute the query 
List<Phrases> phrases = await query.ToListAsync(); 
1

这也应该工作(细节可能是错误的,只是概念):

// common filters here: 
var filtered = db.Phrases 
     .Where(w => (w.EnglishAscii >= es1 && w.EnglishAscii <= ee1) || (w.EnglishAscii >= es2 && w.EnglishAscii <= ee2)) 
     .Where(w => (w.RomajiAscii >= rs1 && w.RomajiAscii <= re1) || (w.RomajiAscii >= rs2 && w.RomajiAscii <= ee2)) 
     .Where(w => (options.CreatedBy == 0 || w.CreatedBy == options.CreatedBy)) 
     .Where(w => (options.ModifiedBy == 0 || w.ModifiedBy == options.ModifiedBy)) 
     .Where(w => (options.JLPT == 0 || w.JLPT == options.JLPT)); 

    // specific filters 
    switch (options.PhraseTypeSelectId) 
    { 
     case 0: 
      filtered = filtered 
       .Where(w => ((w.CategoryId == options.CategorySelectId || options.CategorySelectId == null) || 
         (w.ChapterId == options.ChapterSelectId || options.ChapterSelectId == null))) 
      break; 
     case 1: 
      filtered = filtered 
       .Where(w => ((w.CategoryId == options.CategorySelectId || options.CategorySelectId == null))) 
      break; 
     case 2: 
      // ??? 
      break; 
     default: 
      return BadRequest(); 
    } 
    var phrases = async filtered 
     .AsNoTracking() 
     .ToListAsync(); 
    return Ok(phrases); 
2

如果我理解正确,问题是如何构建动态过滤器。要做到这一点,你可以用基本的IQueryable<T>开始,基于参数的条件申请Where这样的:

var query = db.Phrases.AsQueryable(); 

bool categoryFilter = options.CategorySelectId != null && options.PhraseTypeSelectId != 2; 
bool chapterFilter = options.ChapterSelectId != null && options.PhraseTypeSelectId != 1; 
if (categoryFilter && chapterFilter) query = query 
    .Where(w => w.CategoryId == options.CategorySelectId || w.ChapterId == options.ChapterSelectId); 
else if (categoryFilter) query = query 
    .Where(w => w.CategoryId == options.CategorySelectId); 
else if (chapterFilter) query = query 
    .Where(w => w.ChapterId == options.ChapterSelectId); 

query = query 
    .Where(w => (w.EnglishAscii >= es1 && w.EnglishAscii <= ee1) || (w.EnglishAscii >= es2 && w.EnglishAscii <= ee2)) 
    .Where(w => (w.RomajiAscii >= rs1 && w.RomajiAscii <= re1) || (w.RomajiAscii >= rs2 && w.RomajiAscii <= ee2)); 

if (options.CreatedBy != 0) query = query 
    .Where(w => w.CreatedBy == options.CreatedBy); 

if (options.ModifiedBy != 0) 
    query = query.Where(w => w.ModifiedBy == options.ModifiedBy); 

if (options.JLPT != 0) 
    query = query.Where(w => w.JLPT == options.JLPT); 

var phrases = await query 
    .AsNoTracking() 
    .ToListAsync(); 

return Ok(phrases); 
相关问题