2016-03-25 3 views
1

С помощью следующейНевозможно создать нулевое постоянное значение типа 'System.Int32 []'.

PagedData.Products = from p in db.Products 
            where (from m in p.Manufacturers 
              where model.man.Contains(m.ManufacturerID) 
              select m).Any() 
            where (from s in p.Sizes 
              where model.size.Contains(s.SizeID) 
              select s).Any() 
            where (from c in p.Colors 
              where model.color.Contains(c.ColorID) 
              select c).Any() 
            select p; 

я получаю эту ошибку

Невозможно создать нулевое постоянное значение типа 'System.Int32 []'. Только типы объектов, типы перечисления или примитивные типы поддерживаются в в этом контексте.

У меня есть точка ошибки, но я не могу понять, как ее исправить. model.manmodel.size и model.color - это массивы целых чисел, которые также могут быть нулевыми.

+2

вы пытались проверить нулевые значения, как 'где model.size! = NULL && model.size.Contains (s.SizeID) ' – esiprogrammer

+0

Массивы могут быть пустыми или целыми числами внутри может быть null? Если это первый случай, просто используйте Список вместо этого и сделайте его по умолчанию пустым –

+0

Можете ли вы изменить int массивы на nullable int list (List )? –

ответ

3

Поскольку все условия должны быть истинными, чтобы пройти любой Product вы должны сначала проверить, если все массивы имеют какой-либо контент на все:

if (model.man != null && model.size != null && model.color != null 
     && model.man.Any() && model.size.Any() && model.color.Any()) 
{ 
    PagedData.Products = from p in db.Products ... 

Теперь вы не будете выполнять запрос, если вы знаете заранее, что Безразлично» t вернет любые данные. И он не будет генерировать исключение, потому что вы никогда не запускаете запрос с помощью массивов null.

+0

Это был не я! :) На самом деле не все условия должны быть правдой, я хочу, чтобы было что-то вроде || между предложениями where. – OrElse

+1

Это другая проблема, но есть общий способ сделать это: http: // stackoverflow.com/a/14622200/861716 –

+0

За исключением того, что для этого вам не нужна какая-либо внешняя библиотека - вы назначаете запрос переменной IQueryable и добавляете к этому шаг за шагом. – TomTom

2

Я предпочел бы динамически строить пункт Where используя синтаксис метода и if с, но если вы хотите вставлять условия внутри запроса, вам необходимо убедиться, что IEnumerable s, которые вы используете для Contains критериев не null. И это должно произойти вне запрос:

var man = model.man ?? Enumerable.Empty<int>(); 
var size = model.size ?? Enumerable.Empty<int>(); 
var color = model.color ?? Enumerable.Empty<int>(); 

PagedData.Products = from p in db.Products 
            where (from m in p.Manufacturers 
              where man.Any() && man.Contains(m.ManufacturerID) 
              select m).Any() 
            where (from s in p.Sizes 
              where size.Any() && size.Contains(s.SizeID) 
              select s).Any() 
            where (from c in p.Colors 
              where color.Any() && color.Contains(c.ColorID) 
              select c).Any() 
            select p; 

Обратите внимание, что filter.Any() && filter.Contains(...) не имеет смысла и эквивалентно filter.Contans(...). Если вы хотите игнорировать пустой фильтр, вы должны использовать !filter.Any() || filter.Contans(...).

Так IMO ваш запрос должен быть как этот

var man = model.man ?? Enumerable.Empty<int>(); 
var size = model.size ?? Enumerable.Empty<int>(); 
var color = model.color ?? Enumerable.Empty<int>(); 

PagedData.Products = from p in db.Products 
        where (from m in p.Manufacturers 
          where !man.Any() || man.Contains(m.ManufacturerID) 
          select m).Any() 
        where (from s in p.Sizes 
          where !size.Any() || size.Contains(s.SizeID) 
          select s).Any() 
        where (from c in p.Colors 
          where !color.Any() || color.Contains(c.ColorID) 
          select c).Any() 
        select p; 

или этого

var query = db.Products.AsQueryable(); 
if (model.man != null && model.man.Length > 0) 
    query = query.Where(p => p.Manufacturers.Any(m => model.man.Contains(m.ManufacturerID))); 
if (model.size != null && model.size.Length > 0) 
    query = query.Where(p => p.Sizes.Any(s => model.size.Contains(s.SizeID))); 
if (model.color != null && model.color.Length > 0) 
    query = query.Where(p => p.Colors.Any(c => model.color.Contains(c.ColorID))); 
PagedData.Products = query; 
+0

Я никогда не хотел включать такие вещи, как 'man.Any()' в оператор LINQ, который был переведен на SQL. Вы проверили сгенерированный SQL? Локальная последовательность 'man' должна быть преобразована в структуру таблицы, которая выполняется цепочкой выбора UNION' -d однострочных. Это может сильно повлиять на производительность, когда массивы «большие». Если условия являются дополнительными, конечно, ваш последний фрагмент кода - это путь, хотя вы должны добавить условие, которое не возвращает ничего, если ни один из массивов не имеет содержимого. –

+0

@GertArnold Мне тоже это не нравится, и предпочитаю другой способ, как было сказано в начале. Кроме того, я согласен с тем, что ваш ответ лучше, если OP действительно хочет вернуть пустой набор результатов, как в исходном запросе, но я считаю, что, возможно, он хочет игнорировать фильтры, когда «null» или «empty», и возвращает полный набор в таком случае. Конечно, это мое предположение, но звучит логично для меня :) –

+0

@GertArnold Не следует ли преобразовать локальную последовательность 'man' (которая является списком' int') в константу 'IN (....)'? –

Смежные вопросы