3

我在一个类中有一个方法,它允许我根据一组客户指定的条件返回结果。该方法将客户在前端指定的内容与来自数据库的集合中的每个项目相匹配。在客户未指定任何属性的情况下,将属性的 ID 传递给等于 0 的方法(数据库在所有表上都有一个标识,该标识以 1 为种子并且是增量的)。在这种情况下,应该忽略该属性,例如,如果客户未指定位置,则 customerSearchCriteria.LocationID = 0 进入方法。然后匹配将匹配其他属性并返回与其他属性匹配的所有位置,示例如下:

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{   
    if(customerSearchCriteria.LocationID == 0)
    {         
         return repository.GetAllPetsLinkedCriteria()
                     .Where(x => x.TypeID == customerSearchCriteria.TypeID &&
                                 x.FeedingMethodID == customerSearchCriteria.FeedingMethodID &&
                                 x.FlyAblityID == customerSearchCriteria.FlyAblityID )
                     .Select(y => y.Pet);
    }
}

指定所有条件时的代码如下所示:

private PetsRepository repository = new PetsRepository();

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{            
    return repository.GetAllPetsLinkedCriteria()
                     .Where(x => x.TypeID == customerSearchCriteria.TypeID &&
                                 x.FeedingMethodID == customerSearchCriteria.FeedingMethodID &&
                                 x.FlyAblityID == customerSearchCriteria.FlyAblityID &&
                                 x.LocationID == customerSearchCriteria.LocationID )
                     .Select(y => y.Pet);
}

每次客户没有明确选择他们正在寻找的结果的属性时,我想避免使用一整套if 和 else 语句来满足需求。我可以实现这一目标的最简洁和有效的方法是什么?

4

3 回答 3

2

未选择的标准始终为零,对吗?那么如何获取字段等于条件或条件为零的行。

这应该工作

private PetsRepository repository = new PetsRepository();

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{
    return repository.GetAllPetsLinkedCriteria()
                     .Where(x => (customerSearchCriteria.TypeID == 0 || x.TypeID == customerSearchCriteria.TypeID)&&
                                 (customerSearchCriteria.FeedingMethodID == 0 || x.FeedingMethodID == customerSearchCriteria.FeedingMethodID) &&
                                 (customerSearchCriteria.FlyAblityID == 0 || x.FlyAblityID == customerSearchCriteria.FlyAblityID) &&
                                 (customerSearchCriteria.LocationID == 0 || x.LocationID == customerSearchCriteria.LocationID))
                     .Select(y => y.Pet);
}

或者,如果这是您发现自己经常做的事情,您可以编写一个替代Where扩展方法,该方法要么应用条件,要么在为零时通过,并将调用链接起来,而不是让一个条件与条件相加。然后,您只需在每个查询中对条件 == 0 进行一次比较,而不是对每个不匹配的行进行比较。我不确定这是否值得 -可能的- 边际性能提升,如果您想要性能提升,最好在数据库中应用过滤器。
无论如何,为了教化的目的,它就在这里。. .

static class Extns
{
    public static IEnumerable<T> WhereZeroOr<T>(this IEnumerable<T> items, Func<T, int> idAccessor, int id)
    {
        if (id == 0)
            return items;
        else
            return items.Where(x => idAccessor(x) == id);
    }
}

private PetsRepository repository = new PetsRepository();

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{
    return repository.GetAllPetsLinkedCriteria()
        .WhereZeroOr(x => x.TypeID, customerSearchCriteria.TypeID)
        .WhereZeroOr(x => x.FeedingMethodID, customerSearchCriteria.FeedingMethodID)
        .WhereZeroOr(x => x.FlyAblityID, customerSearchCriteria.FlyAblityID)
        .WhereZeroOr(x => x.LocationID, customerSearchCriteria.LocationID);
}
于 2012-11-11T09:12:13.110 回答
2

看起来您正在使用存储过程,并且您首先获取所有记录,然后进行过滤。我建议您在存储过程级别进行过滤,让数据库完成繁重的工作,并且您需要在后面进行的任何微过滤都会更容易。在您的存储过程中,让您的参数默认为 NULL 并使您的属性可以为标准对象为空,这样您就可以传入值并且存储过程将(应该)被更正以使用这些空值,即

 private PetsRepository repository = new PetsRepository();

    public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
    {
        return repository.GetAllPetsLinkedCriteria(customerSearchCriteria.TypeID,customerSearchCriteria.FeedingMethodID,customerSearchCriteria.FlyAblityID,customerSearchCriteria.LocationID).ToList();
    }
于 2012-11-11T09:21:56.550 回答
2

我没有看到一个优雅的解决方案。可能是这样的:

IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{
    return repository.GetAllPetsLinkedCriteria()
                     .Where(x => 
                      Check(x.TypeID, customerSearchCriteria.TypeID) &&
                      Check(x.FeedingMethodID, customerSearchCriteria.FeedingMethodID) &&
                      Check(x.FlyAblityID, customerSearchCriteria.FlyAblityID) &&
                      Check(x.LocationID, customerSearchCriteria.LocationID))
                     .Select(x => x.Pet);
}

static bool Check(int petProperty, int searchCriteriaProperty)
{
    return searchCriteriaProperty == 0 || petProperty == searchCriteriaProperty;
}
于 2012-11-11T10:13:05.840 回答