LINQ в Entity Framework добавляет в предложение DATETIME WHERE

#c# #entity-framework #linq #datetime #lambda

#c# #entity-framework #linq #datetime #лямбда

Вопрос:

Я пытаюсь создать предложение WHERE во время выполнения. Я создал запрос с начальным предложением WHERE:

 var origSQL = (from ....
               join ...
               where ...
               select new { ... } ); 
  

и будет добавлено следующее WHERE в origSQL:

 var endDate = (from table1 in db.Table1
               join aliasTable1 in db.Table1 on table1.id equals aliasTable1.id
               where aliasTable1.anotherId  == anInputStr
               amp;amp; (table1.field1 == aliasTable1.field1)
               select DbFunctions.TruncateTime(aliasTable1.endDate)).Max();
...
  

Конечная дата будет нуждаться в дальнейшем уточнении перед присоединением к исходному WHERE, например:

 if (!string.IsNullOrEmpty(anotherInputStr) amp;amp; (anotherInputStr == "FOO"))
   endDate = endDate.Where ( a=> aliasTable1.GRADE == "F" );
  

При этом я получаю сообщение об ошибке:

 DateTime does not contain a definition for Where accepting a first argument of type DateTime
  

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

 var endDateCriteria = from table1 in db.Table1
               join aliasTable1 in db.Table1 on table1.id equals aliasTable1.id
               where aliasTable1.anotherId  == anInputStr
               amp;amp; (table1.field1 == aliasTable1.field1)

if (!string.IsNullOrEmpty(anotherInputStr) amp;amp; (anotherInputStr == "FOO"))
   endDateCriteria = endDateCriteria .Where ( a=> aliasTable1.GRADE == "F" );
  

Но

 .Where
  

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

Добавлено, что это изначально самосоединение. Исходный динамический SQL выглядит следующим образом

 origSQL := ' AND table1.endDate = (
                 SELECT MAX(endDate)
                 FROM table1 aliasTable1   
                 WHERE aliasTable1.ID = table1.ID)
  

И я пытаюсь добавить дополнительные предложения WHERE к этому, которые затем полностью будут добавлены к основному запросу. Я не знаю синтаксиса для этого.

Комментарии:

1. Можете ли вы показать, какой тип данных endDateCriteria ?

2. Ваш .Max() гарантирует, что вы не возвращаете перечислимые или запрашиваемые, а скорее одну дату, на которую вы не можете выполнять Where() или аналогичные функции linq. Возможные решения: выберите несколько значений вместо только даты или вместо .Max(); попытки ToList(); выполнить проверку.

3. Какая сущность обладает этим GRADE свойством? В вашем втором запросе вы не опубликовали то, что выбираете (вы всегда должны что-то выбирать).

4. @Jacky: это тип DateTime, возвращаемый из предложения select .

5. @Andrew: это еще одно поле в (псевдонимной) самосоединяющейся таблице table1, но это условие, которое должно быть включено только в том случае, если выполняется <предикат> .

Ответ №1:

Каждый запрос должен иметь select , который будет определять, что будет содержать ваша переменная. Во втором примере у вас его нет, поэтому он не компилируется. Вы должны сделать что-то вроде этого:

 var endDateCriteria = from table1 in db.Table1
                        join aliasTable1 in db.Table1 on table1.id equals aliasTable1.id
                        where aliasTable1.anotherId == anInputStr
                        amp;amp; (table1.field1 == aliasTable1.field1)
                        select new { table1, aliasTable1 };

if (!string.IsNullOrEmpty(anotherInputStr) amp;amp; (anotherInputStr == "FOO"))
    endDateCriteria = endDateCriteria.Where(q => q.aliasTable1.GRADE == "F");

if (somethingElse)
    endDateCriteria = endDateCriteria.Where(q => q.aliasTable1.field1 > value);

if (otherCondition)
    endDateCriteria = endDateCriteria.Where(q => q.table1.field2 != value2);

DateTime result = endDateCriteria.Max(q => q.aliasTable1.endDate).Date;
  

Здесь я сохраняю endDateCriteria обе таблицы в анонимном объекте, поэтому позже я могу продолжить использовать обе таблицы для своих условий, и в итоге я получаю максимальную дату. Я не вижу необходимости использовать TruncateTime .

Ответ №2:

Отредактированный ответ с условием, упомянутым в комментарии оригинальным постером:

 var endDates = (from table1 in db.Table1
               join table2 in db.Table2 on table1.id equals table2.id
               where table2.anotherId  == anInputStr
               amp;amp; (table1.field1 == table2.field1);
if(YOUR CONDITION)
{
 endDates = endates.Where(e=> e.).Grade == "F")
}
var endate = from endates select DbFunctions.TruncateTime(table2.endDate)).Max();
  

Изначально вы работали с одним объектом (таблица максимальных значений 2.enddate) .Where , который действует на коллекцию.

 var endDate = (from table1 in db.Table1
               join table2 in db.Table2 on table1.id equals table2.id
               where table2.anotherId  == anInputStr
               amp;amp; (table1.field1 == table2.field1)
  

amp;amp; таблица (я не знаю, какая таблица).Оценка == «F»

                select DbFunctions.TruncateTime(table2.endDate)).Max();
  

Комментарии:

1. Я исправил, чтобы проиллюстрировать, где должна быть получена оценка, если условие выполнено. Я должен добавить предложение условно и не нашел синтаксиса.

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