我这里有这个代码。我认为这不是非常有效,我想知道是否有一种方法可以让我这样做。所以.Where子句在开头或结尾添加而不是重复三次。如果有人能给我任何建议并告诉我如何做到这一点,我将不胜感激:
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语句,它与与PhraseTypeSelectId相关的.Where子句变得非常混乱
答案 0 :(得分: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();
答案 1 :(得分:3)
您可以使用扩展方法.AsQueryable()
这将返回linq语句的前一部分作为可查询表达式,如果需要允许进一步操作和转换。
例如
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
答案 2 :(得分: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);
答案 3 :(得分:1)
IQueryable
或IEnumerable
上的LINQ查询在您实际迭代结果之前不会被评估 - 通过循环结束,或调用ToList()
或类似的结果。
因此,您可以分阶段构建事物,例如:
var exp = dbcontext.Logs.Where(x => x.Code == 4);
它不会执行数据库上的任何代码。然后你可以稍后说:
var logs = await exp.Where(x => x.Module == "AUTH").ToListAsync();
由于ToListAsync()
,将执行查询。
这方面的巨大优势是能够使用合理的方法分阶段构建查询(而不是切割SQL的字符串),并相信实体框架或您正在使用的任何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();
答案 4 :(得分: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);