【问题标题】:Building Entity Framework Linq queries with variables使用变量构建实体框架 Linq 查询
【发布时间】:2020-08-31 06:53:26
【问题描述】:

我正在努力为我偶尔遇到的一些事情找到最佳实践,每次我都觉得这不是实现我想做的最优雅、最好和最肯定有效的方法.

考虑一下:

型号:

public class User
{
  public string firstName {get; set;}
  public string lastName {get; set;}
  public string middleName {get; set;}
  public string someName {get; set;}

 // etc... up to, let's say 20 inputs
}

html:

<input type="text" name="firstName">
<input type="text" name="lastName" disabled>
<input type="text" name="middleName" disabled>
<input type="text" name="someName" disabled>```

控制者:

private dbcontext db = new dbcontext();
List<User> users = db.Users.Where( x => firstName != null && x.firstName == fisrtName ||
                   lastName != null && x.lastName == lastName ||
// and so on, and so on...

现在,另一端的一些人可以选择启用上述输入并使用传递的参数为某些用户查询数据库。

我希望现在您已经明白我在这里难以理解的内容了。我喜欢只使用已启用的变量并将它们组合成 AND 查询而不是 OR。我知道,我知道 - && 用于这件事,但这并不像我想要的那样工作。

我不想使用 if 语句检查每个变量是否为 null,然后为可能发生的每个场景创建查询。

如果那是转发,我很抱歉,但我找不到答案。

【问题讨论】:

  • 不应该是x =&gt; (firstName == null || x.firstName == firstName) &amp;&amp; (lastName == nul || x.LastName == lastName) &amp;&amp; ....
  • 你真的找不到答案吗?这是经常被问到的。尝试在搜索中包含“谓词构建器”。

标签: c# html entity-framework linq model-view-controller


【解决方案1】:

型号

public class User
{
  public string firstName {get; set;}
  public string lastName {get; set;}
  public string middleName {get; set;}
  public string someName {get; set;}

 // etc... up to, let's say 20 inputs
}

HTML

@model YourModel
@Html.TextBoxFor(m => m.firstName, "", new { })
@Html.TextBoxFor(m => m.lastName, "", new { @disabled = true })
@Html.TextBoxFor(m => m.middleName, "", new { @disabled = true })
@Html.TextBoxFor(m => m.someName, "", new { @disabled = true })

控制器

        private readonly YourContext _db;

        public YourController(YourContext db)
        {
            _db = db;
        }
        [HttpGet]
        public async Task<IActionResult> YouReturningView()
        {
          var model = await _db.YourDbSet.Where(Your Where).FirstAsync();
          return View(model);
        }

我认为这就是优雅而正式的方式。生成的 Html 将包含所有需要的属性,就像您的班级一样。

【讨论】:

    【解决方案2】:

    如果要根据启用的字段查询记录,则需要在linq查询中使用动态where子句

    只有当字段中存在数据时,才能使用以下查询动态启用 where 子句。如果 firstName 中存在数据,它将根据记录检查 firstName 的记录,否则它将返回 true 并进入下一个条件。如果firstName 和middleName 都有数据,那么它将根据firstName 和middleName 获取记录。所有其他领域的方法相同

    如果所有字段中都没有数据,那么它将返回数据库中的所有记录

    List<User> users = (from u in db.Users
                       where 
                       (firstName != null? u.firstName == firstName:true) &&
                       (lastName != null? u.lastName == lastName:true) &&
                       (middleName != null ? u.middleName == middleName:true) &&
                       (someName != null ? u.someName == someName:true)
    
                       select new User
                       {
                           firstName = u.firstName,
                           lastName = u.lastName,
                           middleName = u.middleName,
                           someName = u.someName
    
    
                       }).ToList();
    

    【讨论】:

    • 这正是我在这个特定示例中所需要的,并且可以完美运行。谢谢你,Ambareesh!
    【解决方案3】:

    假设 Web 请求已转换为您的 User 模型的实例,您可以先进行一些反思以完成此操作。

    首先,让我们假设该对象作为 User 对象从 Web 请求中返回,该对象可能会或可能不会填充所有字段。我们就叫它SearchUser吧。

    首先,我们可以通过反射User 类型来获取所有属性。

    var filledProperties = typeof(User).GetProperties()
        .Where(t => t.GetValue(SearchUser) != null 
        && !string.IsNullOrEmpty(t.GetValue(SearchUser).ToString()));
    

    这样做是检查SearchUser 对象并返回具有非空值且不是空字符串的PropertyInfo 对象数组。这意味着您的 Web 请求可能具有 20 个属性中的 5 个或全部 20 个属性的值,但是填充的许多属性最终会出现在此数组中。

    接下来,我们可以使用它来查询您的数据库。

    List<User> users = db.Users
        .Where(u => filledProperties.Any(p => p.GetValue(u) != null
        && p.GetValue(u).ToString()
        == p.GetValue(SearchUser).ToString()))
        ToList();
    

    我们在这里所做的是检查每个数据库用户,如果其中的任何属性与以下两个匹配,则返回它:

    • filledProperties 中与测试属性匹配的 DB 属性不为空,并且
    • DB 中的匹配属性与SearchUser 同名对象中的属性具有相同的值。

    这种方法的优点是,无论您的User 类中有多少字符串属性可用,都可以使用,并且您不需要更改任何查询代码。此外,如果您的某些属性在 SearchUser 或 Database 对象中为空或为空,它也可以工作。

    当然,缺点是大量使用反射。这将是一个繁重的查询,因此如果您有很多并发请求或有大量用户表,这可能并不理想。在这种情况下,您可能会考虑在 ElastiSearch 之类的工具中隐藏数据库数据,以便您可以在更适合该任务的工具上更快地运行搜索。但这取决于您,但这可以使您的示例正常工作。

    【讨论】:

    • 这就像一个魅力但是虽然它不能在这个特定的例子中使用,因为我没有将 webrequest 转换为用户模型,因为混合中有很多其他参数。尽管我已将上面的回复标记为我的问题的答案,但我会说这是迄今为止最优雅的解决方案,我感谢您,先生!
    猜你喜欢
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    相关资源
    最近更新 更多