Поиск с кодом фильтров


У меня этот метод для поиска в БД с помощью фильтров мне было интересно, если кто-то думает как и я, что этот код является избыточным, а во-вторых, если у вас есть какие-либо предложения, чтобы сократить код.

private const string NO_FILTER = "No filter";

[DataObjectMethod(DataObjectMethodType.Select)]
public static List<Part> GetPartsSearch(string partNumber, string modelNumber, string slotNumber, string yardNumber, int commodityId, string description)
{
    using (var context = new EntitiesModel())
    {
        IQueryable<Part> parts;

        if (slotNumber != NO_FILTER)
        {
            if (modelNumber != "0")
            {
                if (yardNumber != NO_FILTER)
                {
                    if (commodityId > 0)
                    {
                        // Have slot, model, yard and commodity
                        parts = from part in context.Parts
                                join partModel in context.PartsByModels on part.PartNumber equals
                                    partModel.PartNumber
                                join partSlot in context.PartsBySlots on part.PartNumber equals
                                    partSlot.PartNumber
                                join partYard in context.PartsByYards on part.PartNumber equals
                                    partYard.PartNumber
                                join commodity in context.Commodities on part.CommodityId equals
                                    commodity.CommodityID
                                where partSlot.SlotNumber == slotNumber
                                      && partModel.ModelNumber == modelNumber
                                      && partYard.YardNumber == yardNumber
                                      && commodity.CommodityID == commodityId
                                select part;
                    }
                    else
                    {
                        //Have slot, model and yard
                        parts = from part in context.Parts
                                join partModel in context.PartsByModels on part.PartNumber equals
                                    partModel.PartNumber
                                join partSlot in context.PartsBySlots on part.PartNumber equals
                                    partSlot.PartNumber
                                join partYard in context.PartsByYards on part.PartNumber equals
                                    partYard.PartNumber
                                where partSlot.SlotNumber == slotNumber
                                      && partModel.ModelNumber == modelNumber
                                      && partYard.YardNumber == yardNumber
                                select part;
                    }
                }
                else
                {
                    //have slot, model and commodity
                    if (commodityId > 0)
                    {
                        parts = from part in context.Parts
                                join partModel in context.PartsByModels on part.PartNumber equals
                                    partModel.PartNumber
                                join partSlot in context.PartsBySlots on part.PartNumber equals
                                    partSlot.PartNumber
                                join commodity in context.Commodities on part.CommodityId equals
                                    commodity.CommodityID
                                where partSlot.SlotNumber == slotNumber
                                      && partModel.ModelNumber == modelNumber
                                      && commodity.CommodityID == commodityId
                                select part;
                    }
                    else
                    {
                        //Have slot and model
                        parts = from part in context.Parts
                                join partModel in context.PartsByModels on part.PartNumber equals
                                    partModel.PartNumber
                                join partSlot in context.PartsBySlots on part.PartNumber equals
                                    partSlot.PartNumber
                                where partSlot.SlotNumber == slotNumber
                                      && partModel.ModelNumber == modelNumber
                                select part;
                    }
                }

            }
            else if (yardNumber != NO_FILTER)
            {
                if (commodityId > 0)
                {
                    //Have slot yard and commodity    
                    parts = from part in context.Parts
                            join partSlot in context.PartsBySlots on part.PartNumber equals
                                partSlot.PartNumber
                            join partYard in context.PartsByYards on part.PartNumber equals
                                partYard.PartNumber
                            join commodity in context.Commodities on part.CommodityId equals
                                   commodity.CommodityID
                            where partSlot.SlotNumber == slotNumber
                                  && partYard.YardNumber == yardNumber
                                  && commodity.CommodityID == commodityId
                            select part;
                }
                else
                {
                    //Have slot and yard
                    parts = from part in context.Parts
                            join partSlot in context.PartsBySlots on part.PartNumber equals
                                partSlot.PartNumber
                            join partYard in context.PartsByYards on part.PartNumber equals
                                partYard.PartNumber
                            where partSlot.SlotNumber == slotNumber
                                  && partYard.YardNumber == yardNumber
                            select part;
                }
            }
            else
            {
                if (commodityId > 0)
                {
                    parts = from part in context.Parts
                            join partSlot in context.PartsBySlots on part.PartNumber equals
                                partSlot.PartNumber
                            join commodity in context.Commodities on part.CommodityId equals
                                   commodity.CommodityID
                            where partSlot.SlotNumber == slotNumber
                                  && commodity.CommodityID == commodityId
                            select part;
                }
                else
                {
                    parts = from part in context.Parts
                            join partSlot in context.PartsBySlots on part.PartNumber equals
                                partSlot.PartNumber
                            where partSlot.SlotNumber == slotNumber
                            select part;
                }
            }
        }
        else if (modelNumber != "0")
        {
            if (yardNumber != NO_FILTER)
            {
                // Have model, yard and commodity
                if (commodityId > 0)
                {
                    parts = from part in context.Parts
                            join partModel in context.PartsByModels on part.PartNumber equals
                                partModel.PartNumber
                            join partYard in context.PartsByYards on part.PartNumber equals
                                partYard.PartNumber
                            join commodity in context.Commodities on part.CommodityId equals
                                  commodity.CommodityID
                            where partModel.ModelNumber == modelNumber
                                  && partYard.YardNumber == yardNumber
                                   && commodity.CommodityID == commodityId
                            select part;
                }
                else
                {
                    // Have model and yard
                    parts = from part in context.Parts
                            join partModel in context.PartsByModels on part.PartNumber equals
                                partModel.PartNumber
                            join partYard in context.PartsByYards on part.PartNumber equals
                                partYard.PartNumber
                            where partModel.ModelNumber == modelNumber
                                  && partYard.YardNumber == yardNumber
                            select part;
                }
            }
            else
            {
                if (commodityId > 0)
                {
                    // Have model and commodity
                    parts = from part in context.Parts
                            join partModel in context.PartsByModels on part.PartNumber equals
                                partModel.PartNumber
                            join commodity in context.Commodities on part.CommodityId equals
                                 commodity.CommodityID
                            where partModel.ModelNumber == modelNumber
                             && commodity.CommodityID == commodityId
                            select part;
                }
                else
                {
                    // Have model
                    parts = from part in context.Parts
                            join partModel in context.PartsByModels on part.PartNumber equals
                                partModel.PartNumber
                            where partModel.ModelNumber == modelNumber
                            select part;
                }
            }
        }
        else if (yardNumber != NO_FILTER)
        {
            if (commodityId > 0)
            {
                //have yard and commodity
                parts = from part in context.Parts
                        join partYard in context.PartsByYards on part.PartNumber equals
                            partYard.PartNumber
                        join commodity in context.Commodities on part.CommodityId equals
                                 commodity.CommodityID
                        where partYard.YardNumber == yardNumber
                          && commodity.CommodityID == commodityId
                        select part;
            }
            else
            {
                // Have yard
                parts = from part in context.Parts
                        join partYard in context.PartsByYards on part.PartNumber equals
                            partYard.PartNumber
                        where partYard.YardNumber == yardNumber
                        select part;
            }
        }
        else if (commodityId > 0)
        {
            // Have commodity
            parts = from part in context.Parts

                    join commodity in context.Commodities on part.CommodityId equals
                             commodity.CommodityID
                    where commodity.CommodityID == commodityId
                    select part;
        }
        else
        {
            parts = from part in context.Parts
                    select part;
        }

        if (partNumber != "0")
        {
            parts = parts.Where(p => p.PartNumber.ToLower().Contains(partNumber.ToLower()));
        }

        if(!string.IsNullOrEmpty(description))
        {
            parts = parts.Where(p => p.Description.ToLower().Contains(description.ToLower()));
        }

        parts = parts.OrderBy(p => p.PartNumber);

        return parts.ToList();
    }
}


1837
2
задан 16 декабря 2011 в 11:12 Источник Поделиться
Комментарии
2 ответа

Это, безусловно, чрезмерное. :)

Я бы начал искать в том, должен ли быть один метод для получения данных без товарного фильтра, и один способ для тех, с товаром.

Я бы поставил в любом случае каждый запрос в отдельный метод. Что даст вам совсем немного более читабельным основная функция(ы).

Но честно говоря, я удивляюсь, почему вы не имеете свойства навигации на вашем организме, и просто eagerload их .Включить (если эф) или использовать параметры dataloadoptions, позволяющие установить (если L2S).
Таким образом, вы могли угробить все присоединяется от всех запросов.

Также, если вы измените синтаксис расширений, вы можете добавить, где заявления для запросов.

Например (и EntityFramework eagerloading):

var queryable = context.Parts;
if (shouldIncludeModel)
queryable = queryable.Include("Model");
if (model > 0)
queryable = queryable.Where(p => p.Model.Id == model);
if (shouldIncludeYard)
queryable = queryable.Include("Yard");
if (yard > 0)
queryable = queryable.Where(p => p.Yard.Id == yard);

return queryable.ToList();

и т. д.

Это должно быть далее переработан на много лучше, по крайней мере, разделены на методы, отвечающие за каждой из связанных сущностей.
В любом случае, я думаю, что вы получите совсем немного короче способов делать это.

Опираясь на предложение palacsints, вы также можете проверить, как построить LINQ-выражений вручную, но это довольно продвинутый и громоздким.
Есть некоторая информация вот: http://msdn.microsoft.com/en-us/library/bb397951.aspx

1
ответ дан 16 декабря 2011 в 02:12 Источник Поделиться

Я попробуйте создать класс построитель запросов, который хранит операторы join и где условия и позже построить весь запрос из хранимой заявления. Пример псевдокода:

public class QueryBuilder {
List<String> joins;
List<String> whereConditions;

...

public void addJoin(final String join) {
joins.add(join);
}

public void addWhereCondition(final String condition) {
whereConditions.add(condition);
}

public String buildQuery() {
final StringBuilder result = new StringBuilder();
result.append("...");
for (final String join: joins) {
result.append(join);
}
result.append("WHERE ");
for (final String condition: whereConditions) {
result.append(condition);
// TODO: handle &&s here
}

return result.toString();
}
}

Я предполагаю, что то, как это возможно в C# тоже. Затем, ИФС может быть переписан следующим образом:

if (commodityId > 0) {
queryBuilder.addJoin("join commodity in context.Commodities on part.CommodityId
equals commodity.CommodityID");
queryBuilder.addWhere("commodity.CommodityID == commodityId");
}

if (yardNumber != NO_FILTER) {
queryBuilder.addJoin("join partYard in context.PartsByYards on part.PartNumber
equals partYard.PartNumber");
queryBuilder.addWhere("partYard.YardNumber == yardNumber");
}

Это позволит уменьшить сложность cyclomatic и сделать код более удобным для чтения.

0
ответ дан 16 декабря 2011 в 12:12 Источник Поделиться