Формат динамического запроса IQueryable со строками и датами

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

Это мой код:

string userFilter = string.Empty;
string var1 = "3";
string var2 = "54";
string var3 = "Doe, John";
DateTime var4 = DateTime.Now();

IQueryable<MyClass> query = await _context.Table.GetData();

if (!string.IsNullOrEmpty(var1)) 
{
    userFilter = " column1 == " + var1 + " &&"; 
}; //This works

if (!string.IsNullOrEmpty(var2)) 
{
    userFilter = userFilter + " column2 == " + var2 + " &&"; 
}; //This works

if (!string.IsNullOrEmpty(var3)) 
{
    userFilter = userFilter + " column3 == \"" + var3 + "\" &&"; 
}; //Works

if (!string.IsNullOrEmpty(var4)) 
{
    userFilter = userFilter + " column4 == " + var4 + " &&"; 
}; //Doesn't work

userFilter = userFilter.TrimEnd('&');
query = query.Where(userFilter);

var myData = query.ToList();  

Первые два «если» работают правильно, или любые другие с числами в виде строк, но реальные строки или даты — нет. Что мне не хватает?

Спасибо!

Есть ли причина, по которой вы не можете использовать строго типизированные методы Linq на основе Expression<Func<>>? Я не понимаю, как строковые выражения DynamicLinq помогут вам здесь...

Dai 17.08.2024 02:07

@Dai Честно говоря, мне проще сделать это так. Я понял, как обращаться со строками, но мне все еще нужна помощь с датами.

Diomedes 17.08.2024 03:16

Я мог бы предложить использовать yourDateTimeValue.ToString( "o", CultureInfo.InvariantCulture ) - строка формата "o" предназначена для «туда и обратно», что означает отсутствие потери точности и всегда преобразуется в формат ISO 8601 / RFC 3339, который является однозначным и большинство систем принимают «как есть» - я предполагаю, что вы Однако понадобятся разделительные кавычки или что-то подобное.

Dai 17.08.2024 03:19

Пожалуйста, поделитесь, какую именно библиотеку Linq/IQueryable вы используете, в которой есть эти методы Linq на основе String — извините, я ее не узнаю.

Dai 17.08.2024 03:22

@Dai, используя System.Linq.Dynamic.Core;

Diomedes 17.08.2024 03:25

@Дай, изначально это было существо Редмонда weblogs.asp.net/scottgu/…

Svyatoslav Danyliv 17.08.2024 04:25

@SvyatlavDanyliv Я ем свои слова :)

Dai 17.08.2024 04:27

Если вы посмотрите на значение userFilter, вы увидите, что проблема с var4 заключается в том, что вы создаете строку запроса, содержащую строку даты без кавычек. Но, как говорит @Dai, вам лучше использовать формат даты, не зависящий от культуры. См. рабочий пример dotnetfiddle.net/AFPWru, и я также включил тот же запрос с использованием динамического linq с параметрами (что лучше, но по-прежнему создает аналогичный sql), и если вы знаете имена столбцов, тот же запрос без использование динамического linq, что еще лучше, поскольку оно генерирует лучший sql.

sgmoore 18.08.2024 14:09

@sgmoore Первое, что я попробовал, прежде чем опубликовать свой вопрос, — это использовать \"" + ... + "\". Я также пробовал использовать параметры. В обоих случаях я получаю «Номер ошибки: 241, Состояние: 1, Класс: 16». Итак, я проверяю, как выглядит генерируемый SQL, и выглядит следующим образом: SELECT * From MyTable AS [d] WHERE [d].[MyDate] = '2024-07-01T00:00:00.0000000' Я проверил в базе данных - это не нравится такой формат даты. Но по вашим рекомендациям мне удалось доработать код и заставить его работать. Спасибо.

Diomedes 19.08.2024 17:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Библиотека System.Linq.Dynamic.Coreиспользует собственный синтаксис для значений DateTime, который напоминает вызовы ctor, например:

context.Customers.Where("DateTimeProperty >= DateTime(2024,8,16,18,33,0)").ToList();

...но лучше использовать параметры вида @<n>, где <n> — целое число:

DateTime now = DateTime.UtcNow;
context.Customers.Where("DateTimeProperty >= @0", now).ToList();

// Protip: For greater readability, define this extension method:
public static class StringExtensions
{
    public static Boolean IsSet( [NotNullWhen(true)] this String? s ) => !String.IsNullOrWhiteSpace( s );
}

//

String   var1 = "3";
String   var2 = "54";
String   var3 = "Doe, John";
DateTime var4 = DateTime.UtcNow();

IQueryable<MyClass> query = await _context.Table.GetData();

////////
if ( var1.IsSet() ) query = query.Where( "column1 == @0", var1 );
if ( var2.IsSet() ) query = query.Where( "column2 == @0", var2 );
if ( var3.IsSet() ) query = query.Where( "column3 == @0", var3 );
                   query = query.Where( "column4 == @0", var4 );
////////

var myData = query.ToList();

Приведенные выше query = query.Where(...) утверждения будут объединены в AND термины. А если вам нужна OR логика, вы не можете использовать PredicateBuilder.Or, потому что это не Func<T,Boolean> или Expression<Func<>> методы, но мы можем взломать ее с помощью .Union:

(Непроверено, YMMV)

String   var1 = "3";
String   var2 = "54";
String   var3 = "Doe, John";
DateTime var4 = DateTime.UtcNow();

IQueryable<MyClass> q = await _context.Table.GetData();

IQueryable<MyClass> u = q.Where( "1 = 0" ); // <-- This always-false term makes it less-awkward.

////////
if ( var1.IsSet() ) u = u.Union( q.Where( "column1 == @0", var1 ) );
if ( var2.IsSet() ) u = u.Union( q.Where( "column2 == @0", var2 ) );
if ( var3.IsSet() ) u = u.Union( q.Where( "column3 == @0", var3 ) );
                   u = u.Union( q.Where( "column4 == @0", var4 ) );
////////

var myData = u.ToList();

Привет @Dai Спасибо, что нашли время написать код. Я понял, как выполнять запросы с помощью Ling Dynamic без зависания приложения, поэтому оно компилируется и выполняется; однако я получаю сообщение об ошибке. Это та же ошибка, которую я получаю с вашим кодом: Номер ошибки: 241, Состояние: 1, Класс: 16. Это ошибка преобразования даты. Я пробовал отформатировать дату 50 различными способами, но приложение снова зависает без ошибки возврата или продолжает возвращать ту же ошибку.

Diomedes 18.08.2024 01:36

Другие вопросы по теме