一种搜索实体的方法,其特定属性与实体框架中的给定标准相匹配

本文关键字:实体 框架 属性 标准 一种 搜索 方法 | 更新日期: 2023-09-27 18:14:56

好吧,我不确定问题的标题是否足够清楚,但我想不出更简单的解释了。

我正在制作一个ASP的搜索页面。. NET web应用程序。我希望允许用户使用不同的过滤器进行搜索。

我想出了一个方法,根据用户选择的Categories类型过滤Publications(这些是用户将检索的实体)。

List<Publication> publications =
            (from p in GetPublications()
             where categories.Contains((int)p.CategoryId)
             select p).ToList();

上面的linq查询等价于下面的sql查询:

select * from Publication p where p.CategoryId in (@chosenCategoryIds)

一切都很完美,但问题是我想让用户从更多的过滤器中选择,例如,不仅是类别,还有用户,标签,标题等。

如果我想要这个,我应该写很多条件语句来检查用户是否提供了给定的过滤器,比如:

if (categories != null)
{
    var publications = (from p in GetPublications()
                       where categories.Contains((int)p.CategoryId)
                       select p).ToList();
    if (users != null)
    {
        publications = (from p in publications 
                       where users.Contains((int)p.UserId)
                       select p).ToList();
    }
}
else 
{
// Handle other situations..
}

结果是我对不同的过滤器做了相同的事情。我的问题是,是否有人知道或能想到更好的方法来实现这一点?如果没有,让我们看看下面的方法:

public List<InterpretumDAL.Publication> FilterPublications(List<InterpretumDAL.Publication> oldList, int[] values)
{
    List<InterpretumDAL.Publication> newList =
        (from p in oldList
         where values.Contains((int)p.CategoryId)
         select p).ToList();
    return newList;
}

我试图用上面的方法实现的是通过给定的值数组过滤给定的列表。问题是,我不知道如何告诉方法要比较哪个属性,所以我可以这样调用它:

newList = FilterPublications(publications, categories, CATEGORY_PROPERTY_OF_PUBLICATION);
newList = FilterPublications(publications, users, USER_PROPERTY_OF_PUBLICATION);
newList = FilterPublications(publications, tags, TAG_PROPERTY_OF_PUBLICATION);
编辑:

根据LiquidPony的回答,我是这样做的:

var publications = (from p in GetPublications()
                    where (
                    (categories == null || categories.Length == 0 || (p.CategoryId.HasValue && categories.Contains((int)p.CategoryId)))
                    && (users == null || users.Length == 0 || users.Contains(p.UserId))
                    && (tags == null || tags.Length == 0 || tags.Contains(p.TagId))
                    )
                    select p).ToList();

一种搜索实体的方法,其特定属性与实体框架中的给定标准相匹配

根据LiquidPony的回答,我认为使用三元运算符这样做会更好。

var query = from p in GetPublications()
        where (
              (categories != null ? categories.Contains((int)p.CategoryId) : true)
              && (users != null ? users.Contains((int)p.UserId) : true)
              && (tags != null ? tags.Contains((int)p.TagId) : true)
        ) select p;

如果没有提供其中一个变量,该语句将简单地求值为true,而不包括在SQL求值中(据我所知)。

除非绝对必要,否则要避免使用OR。在SQL中,它们的效率非常低,通常您可以找到一种替代方法来获得您想要的结果,而无需使用它们。

最简单的方法是这样做:

var query = from p in GetPublications()
            where (
                  (categories == null || categories.Contains((int)p.CategoryId))
                  && (users == null || users.Contains((int)p.UserId))
                  && (tags == null || tags.Contains((int)p.TagId))
            ) select p;

如果你想匹配所有的条件,那就可以了。如果您希望返回只匹配一个条件的实体,则可以将&&切换为||