使用Entity Framework实现高级搜索的最佳实践是什么?

5
我使用了两种不同的方法来实现高级搜索,每种方法都有其优缺点。
用户可以使用3个参数(姓名,姓氏和手机号码)执行高级搜索。
我尝试的第一种方法是检查用户提供的这些参数中哪些已经提供;这需要我进行8个if和else checks检查(2 ^ 参数数量),并在每个条件中编写一个单独的查询,该查询接受相应的参数。例如,如果用户输入了姓名和姓氏,则查询的where子句将如下所示:
where(x=>x.name.contains(name) && x.familyname.contains(familyname))

如果用户只输入了手机号码,查询语句的where子句将如下所示:

where(x=>x.mobile==mobile)

这种方式的优点是只需一次数据库查询,但缺点是需要编写更多的代码。
第二种方式是我声明了一个 IQueryable<> 对象,并首先以无条件向其中填充数据,然后逐个检查搜索参数,如果有任何参数具有值,则使用该值对 IQueryable 进行过滤,最后执行 .ToList()。这种方式的优点是代码量大大减少,但会导致数据库查询两次,这是一个问题。
以下是第二种方法的代码示例:
List<ShoppingCardForGridView> list_ShoppingCardForGridView = 
    new List<ShoppingCardForGridView>();
IQueryable<ShoppingCardForGridView> outQuery = 
    from x in db.ShoppingCards
    orderby x.TFDateBackFromBank descending
    where x.TFIsPaymentCompleted == true
    select new ShoppingCardForGridView
    {
        Id = x.Id,
        TFCustomerFullName = 
            x.Customer.TFName + " " + x.Customer.TFFamilyName,
        TFDateBackFromBank = x.TFDateBackFromBank.Value,
        TFIsDelivered = x.TFIsDelivered,
        TFItemsPriceToPay = x.TFItemsPriceToPay,
        TFDateBackFromBankPersian = x.TFDateBackFromBankPersian

    };

if (!string.IsNullOrEmpty(CustomerFullName))
{
    outQuery = outQuery.Where(x => 
        x.TFCustomerFullName.Contains(CustomerFullName));
}
if (!string.IsNullOrEmpty(IsDelivered))
{
    bool deliveryStatus = Convert.ToBoolean(IsDelivered);
    outQuery = outQuery.Where(x => x.TFIsDelivered == deliveryStatus);
}
list_ShoppingCardForGridView = outQuery.ToList();

我想知道使用EntityFramework进行高级搜索的更好方法或最佳实践是什么?


我认为这可能更适合于CodeReview - PiousVenom
我看不出你是如何两次访问数据库的。那里只有一个迭代。 - Servy
@SLaks我不认为有这个必要。他已经拥有的代码比手动构建表达式更简单,但同样有效。 - Servy
@Servy 在第二种方式中,当执行查询时:IQueryable<ShoppingCardForGridView> outQuery = from x in db.ShoppingCards ... 它只会访问数据库一次,在这一行代码中:list_ShoppingCardForGridView = outQuery.ToList(); 执行了 .ToList() 操作后,又会再次访问数据库。我的理解正确吗? - gwt
顺便提一句,方法开始时创建新列表没有意义。您从未使用该列表,而且从未向其添加任何内容就将其丢弃。因此请直接删除该行,并在最后一行首次定义局部变量,因为您不需要早期使用它。 - Servy
显示剩余4条评论
1个回答

8
你的第二个解决方案并没有多次访问数据库。请记住,IQueryable对象本身就是一个查询,而不是查询结果。只有在实际迭代查询时才会执行。基于各种if检查条件地追加多个Where子句是更改查询本身,而不是处理查询结果(因为此时还没有结果)。你可以在数据库上使用分析器来验证只执行了一个查询,并且这个查询包含了所有过滤条件。这是一种相当常见的模式;我已经在许多情况下用它来创建自定义搜索页面。

那么我的第二种方式是最佳实践吗? - gwt
@Karamafrooz 这是一种非常好的方式,它明显是正确的,同样有效、可扩展且易于编写,不像第一种方法那样非常繁琐、容易出错且不可扩展。这应该会让决策变得非常明显。 - Servy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接