2016-04-26 16 views
0

我很新的MVC世界,但我一直在做asp.net多年。我用mvc开始这个项目,所以我可以习惯它。我一直在挣扎一些过于复杂的SQL语句LINQ已经产生,我认为我做错了什么。也许它正确地做到这一点,我只是不能从头开始写SQL语句。复杂的MVC LINQ生成的SQL脚本

好的,我的目标是获得这个身份数据库,我已经添加了几个字段,并链接到其他一些表中,如地址和phoneNumbers等。

我正在供应商搜索屏幕上工作,并希望使用LINQ来获取数据。在下面的例子中,一些信息在table1的下拉列表中,并且具有文本搜索选项,允许在主aspnet用户和一些其他表格上的多个字段上“或”搜索。

我希望有人帮我在linq上获得这个简化版本。或者我应该开始写我的SQL和使用,在这里以某种方式(不知道怎么做,在MVC框架,而应该是相当类似的

var VendorRole = await db.Roles.FirstAsync(r => r.Name == "vendor"); 

     var results = db.Users.Include(u => u.table1). 
      Include(u => u.table2).Include(u => u.table3). 
      Include(u => u.table4).Include(u => u.table5). 
      Where(u => u.Roles.Any(s => s.RoleId == VendorRole.Id)); 

     if (id1.HasValue) 
     { 
      results.Where(m => m.table1.First(a => a.id1 == id1) != null); 
     } 

     if (id2.HasValue) 
     { 
      results.Where(m => m.table1.First(a => a.id2 == id2) != null); 
     } 

     if (id3.HasValue) 
     { 
      results.Where(m => m.table1.First(a => a.id3 == id3) != null); 
     } 

     IEnumerable<string> searchTerms = SearchString.Split(' ') 
               .Select(x => x.Trim()); 
     foreach (string term in searchTerms) 
     { 
      if (!string.IsNullOrWhiteSpace(term)) 
      { 
       string captured = term.ToUpper(); 
       results = results.Where(t => (t.field1.ToUpper().Contains(captured) || 
              t.field2.ToUpper().Contains(captured) || 
              t.field3.ToUpper().Contains(captured) || 
              (t.field2 + " " + t.field3).ToUpper().Contains(captured) || 
              t.field4.ToUpper().Contains(captured) || 
              t.field5.ToUpper().Contains(captured) || 
              t.table2.Any(m => (m.field6 + " " + m.field7).ToUpper().Contains(captured)) != null)); 
      } 
     } 


     ViewBag.count = results.Count(); 
     if ((page -1) * 10 > ViewBag.count) 
     { 
      page = (int)Math.Floor((double)ViewBag.count/10); 
     } 
     ViewBag.page = page; 
     return PartialView(await results.OrderBy(m => m.field1 + " " + m.field2 + " " + m.field3).Skip((page - 1) * 10).Take(10).ToListAsync()); 

感谢您花时间帮助。

+0

有多个'Where'子句相当于'AND'操作而不是'OR'。你真的想在_all_条件下使用'OR'吗? – RePierre

回答

1

您的查询看起来现在的样子,每个Where子句在集合上使用AND匹配,而不是OR

如果你真的想用OR代替全部条件,下面应该是有用的。

正如我在another answer中提到的那样,使用PredicateBuilder构建复杂查询谓词的正确方法是使用Linq。在地方有了这个,你可以重构你的代码分为两个部分:

  1. 构建断言对于Where条款和
  2. 查询数据

的代码应该是这样的:

private Expression<Func<User, bool>> BuildIdQuery(
    Expression<Func<User, bool>> predicate, 
    int? id, 
    Func<User, int> propertySelector) 
{ 
    if(id.HasValue) 
    { 
     // First(...) with throw an exception if there are no items 
     // matching the predicate; Any() is the proper way to do it. 
     return predicate.Or(m => m.Any(a => propertySelector(a) == id); 
    } 
    return predicate; 
} 

Expression<Func<User, bool>> BuildSearchTermQuery(
    Expression<Func<User, bool>> predicate, string searchTerm) 
{ 
    if(String.IsNullOrWhiteSpace(searchTerm) 
     return predicate; 
    // You don't need to use ToUpper() unless you 
    // know that your database performs case-sensitive comparison 
    return predicate.Or(m => m.field1.Contains(searchTerm)) 
     .Or(m => m.field2.Contains(searchTerm)); // etc. 
} 

让所有查询看起来像这样:

var predicate = PredicateBuilder.True<User>() 
predicate = BuildIdQuery(predicate, id1, a => a.id1); 
predicate = BuildIdQuery(predicate, id2, a => a.id2); 
foreach(var term in searchTerms) 
{ 
    predicate = BuildSearchTermQuery(predicate, term); 
} 

var results = db.Users 
    .Where(predicate) 
    .Skip(...) 
    .Take(...);  
+0

使用predicatebuilder切换到,谢谢。 – drewex

0

这是给你使用什么样的LINQ或存储过程。 对于数据库中的文本搜索你可以看看Lucene port

我会建议你使用N层到复杂的业务逻辑与表现分离,这将是您轻松改变/优化它稍后。

/// <summary> 
/// Assume you have special class to store users 
/// </summary> 
public class UserBdo 
{ 
    public int id1 { get; set; } 
    public int id2 { get; set; } 
    ...... 
} 

public class PagingParams 
{ 
    public int CurrentPage { get; set; } 
    public int PerPage { get; set; } = 10; 
    /// <summary> 
    /// How many without paging 
    /// </summary> 
    public int TotalResults { get; set; } 
} 

public class UsersBll 
{ 
    public IEnumerable<UserBdo> Search(int? id1, int? id2, int? id3, IEnumerable<string> searchTerms, PagingParams pp) 
    { 
     var results = db.Users.Include(u => u.table1). 
      Include(u => u.table2).Include(u => u.table3). 
      Include(u => u.table4).Include(u => u.table5). 
      Where(u => u.Roles.Any(s => s.RoleId == VendorRole.Id)); 

     if (id1.HasValue) 
     { 
      results.Where(m => m.table1.First(a => a.id1 == id1) != null); 
     } 

     if (id2.HasValue) 
     { 
      results.Where(m => m.table1.First(a => a.id2 == id2) != null); 
     } 

     //results = ... 

     pp.TotalResults = 100; 

     return results.Skip((pp.CurrentPage - 1) * pp.PerPage).Take(pp.PerPage).ToListAsync(); 
    } 
}