Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
2 / 2 / 0
Регистрация: 01.11.2017
Сообщений: 19

Вызов метода Any через Expression

27.03.2024, 12:13. Показов 731. Ответов 9
Метки c# (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!

Возникла проблема с вызовом метода Any через Expression для коллекции внутри коллекции, находил примеры, но они не включали в себя внутреннюю коллекцию

Имеется классы, например Server у него есть свойство:
C#
1
2
public virtual ISet<LineConfig> LineConfigs
{ get; set; } = new HashSet<LineConfig>();
Мне необходимо сделать универсальный метод, который я вызываю через рефлексию, который принимает на вход сущность типа T (LineConfig) и имеет дженерик EntityType(Server):

Метод :
C#
1
private object CheckIsUseCollectionsObject<EntityType>(PropertyInfo property, T entity) where EntityType : ObjectBase
Тело:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var parameter = Expression.Parameter(typeof(EntityType), "x");
var propertyExprDeleted = Expression.Property(parameter, "Deleted"); //x.Deleted
Expression targetDeleted = Expression.Constant(false);
var exprDeleted = Expression.Equal(propertyExprDeleted, targetDeleted); // x.Deleted == false
 
Expression<Func<EntityType, bool>> lambdaFunc = Expression.Lambda<Func<EntityType, bool>>(exprDeleted, parameter);
List<EntityType> objects = //тут с помощью lambdaFunc получаем объекты типа EntityType, все работает на этой строчке корректно.
 
var objectsQuery = objects.AsQueryable();
var parameter1 = Expression.Parameter(objects.GetType(), "x");
var expression = Expression.Property(parameter, property); //x."Collections"
var parameter2 = Expression.Parameter(typeof(T), "t");
var propertyExpr2 = Expression.Property(parameter2, "Deleted"); //t.Deleted
var expr2 = Expression.Equal(propertyExpr2, targetDeleted); // t.Deleted == false
var idPropertyInfo = property.PropertyType.GetGenericArguments()[0].GetProperty("Id");
var anyMethod = typeof(Enumerable).GetMethods().FirstOrDefault(method => method.Name == "Any" && method.GetParameters().Count() == 2);
anyMethod = anyMethod.MakeGenericMethod(typeof(T)); // Any<T>
Expression targetId = Expression.Constant(entity.Id);
var propertyExprCall = Expression.Property(parameter2, idPropertyInfo); //t.Id
var exprId = Expression.Equal(propertyExprCall, targetId); //t.Id == entity.Id
Expression exprAny = Expression.AndAlso(expr2, exprId);
 
var expressionObjects = objectsQuery.Expression;
 
var finalExpr= Expression.Property(expressionObjects, property);
 
var lambda = Expression.Lambda<Func<T, bool>>(exprAny, parameter2); // t=> t.Deleted == false && t.Id == entity.Id
var call = Expression.Call(anyMethod, expression, lambda);//x.LineConfigs.Any(t => ((t.Deleted == False) AndAlso (t.Id == entity.Id)))
 
Expression<Func<EntityType, bool>> lambdaFunc1 = Expression.Lambda<Func<EntityType, bool>>(call, parameter);
var needObjects = lambdaFunc1.Compile();
На 28 строчке я получаю x.LineConfigs.Any(t => ((t.Deleted == False) AndAlso (t.Id == entity.Id))) а необходимо, как я понял:
C#
1
objects.LineConfigs.Any(t => ((t.Deleted == False) AndAlso (t.Id == entity.Id)))
чтобы получить на 30 строчке:
C#
1
x => objects.LineConfigs.Any(t => ((t.Deleted == False) AndAlso (t.Id == 4714705859937280)))
Прошу вас помочь и объяснить, где я не прав. Отдельно прошу уделить мне время гуру Элд Хасп, заранее спасибо!

С уважением,
SMEU
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.03.2024, 12:13
Ответы с готовыми решениями:

Вызов метода в запросе через let
У меня имеется БД (Sqlite) в ней есть таблица, в которой хранятся даты, в виде строк. Мне нужно через LINQ-запрос отфильтровать записи, в...

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

Вызов одного метода через другой
Здравствуйте ! У меня такая проблема: есть событие нажатия на кнопку: private void NewGame_Click(object sender, EventArgs e) ...

9
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
27.03.2024, 22:34
SMEU, чё-то мне кажется вы через чур заморочились.
Что этот код должен сделать?
0
2 / 2 / 0
Регистрация: 01.11.2017
Сообщений: 19
28.03.2024, 10:06  [ТС]
Элд Хасп, он должен проверить используется ли удаляемая сущность в каком либо объекте класса, который содержит коллекцию с типом удаляемой сущности и если мы находим id удаляемой сущности, то запрещаем удаление.
Метод должен запросить у типа EntityType коллекцию с типом T и проверить, с помощью метода Any используется ли сущность типа T у какого-либо объекта типа EntityType.
С не коллекцией проблем нет, все отлично работает, осталось только докрутить этот метод. В системе сейчас возможно удалить сущность, на которую есть действующие ссылки у других сущностей, надо избежать этого.
0
 Аватар для Andrey-MSK
3313 / 2200 / 387
Регистрация: 14.08.2018
Сообщений: 7,404
Записей в блоге: 4
28.03.2024, 10:20
Цитата Сообщение от SMEU Посмотреть сообщение
В системе сейчас возможно удалить сущность, на которую есть действующие ссылки у других сущностей, надо избежать этого.
Данные из СУБД приходят? Если да, то это решается на стороне СУБД созданием нужной связи между таблицами. И тогда, если есть связь, данные верхнего уровня нельзя будет удалить. Удалить можно будет только в том случае, если пойти по связям снизу вверх, удаляя поочерёдно подчинённые записи.

Добавлено через 5 минут
SMEU, А если в связи задан режим CASCADE DELETE, то соответственно при удалении данных верхнего уровня каскадно удалятся все данные нижнего. Опасный момент и его надо учитывать.
0
2 / 2 / 0
Регистрация: 01.11.2017
Сообщений: 19
28.03.2024, 11:37  [ТС]
Всем большое спасибо!
На само деле сам себе перемудрил.
Вот рабочий код, который вызывается через рефлексию и принимает дженерик типа EntityType (он содержит коллекцию типа Т), у которого будут искаться ссылки на используемые объекты классов типа Т:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private object CheckIsUseCollectionsObject<EntityType>(PropertyInfo property, T entity) where EntityType : ObjectBase
{
    var parameter = Expression.Parameter(typeof(EntityType), "x");
    var propertyExprDeleted = Expression.Property(parameter, "Deleted"); //x.Deleted
    Expression targetDeleted = Expression.Constant(false);
    var exprDeleted = Expression.Equal(propertyExprDeleted, targetDeleted); // x.Deleted == false
    var expression = Expression.Property(parameter, property); //x."Collections"
    var parameter2 = Expression.Parameter(typeof(T), "t");
    var propertyExpr2 = Expression.Property(parameter2, "Deleted"); //t.Deleted
    var expr2 = Expression.Equal(propertyExpr2, targetDeleted); // t.Deleted == false
    // таргет для сравнения сущности
    var idPropertyInfo = property.PropertyType.GetGenericArguments()[0].GetProperty("Id");
    var anyMethod = typeof(Enumerable).GetMethods().FirstOrDefault(method => method.Name == "Any" && method.GetParameters().Count() == 2);
    anyMethod = anyMethod.MakeGenericMethod(typeof(T)); // Any<T>
    Expression targetId = Expression.Constant(entity.Id);
    var propertyExprCall = Expression.Property(parameter2, idPropertyInfo); //t.Id
    var exprId = Expression.Equal(propertyExprCall, targetId); //t.Id == entity.Id
    Expression exprAny = Expression.AndAlso(expr2, exprId);
    
    var parametrFinal = Expression.Parameter(typeof(EntityType), "objects");
    var lambda = Expression.Lambda<Func<T, bool>>(exprAny, parameter2); // t=> t.Deleted == false && t.Id == entity.Id
    var call = Expression.Call(anyMethod, expression, lambda);//x.LineConfigs.Any(t => ((t.Deleted == False) AndAlso (t.Id == entity.Id)))
    Expression exprFinal = Expression.AndAlso(call, exprDeleted);//x.LineConfigs.Any(t => ((t.Deleted == False) AndAlso (t.Id == entity.Id))) AndAlso (x.Deleted == False))
 
    Expression<Func<EntityType, bool>> lambdaFunc = Expression.Lambda<Func<EntityType, bool>>(exprFinal, parameter);
    var objects = Execute(() => _repository.Query<EntityType>(lambdaFunc).ToList(), false);
 
    if (!objects.Any())
        return true;
    else
        return false;
}
2
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
28.03.2024, 21:15
Цитата Сообщение от SMEU Посмотреть сообщение
Вот рабочий код,..
Замечательно, похвально, что сами разобрались.

Но всё же я остаюсь при своём мнении - перемудрили.
Если это нужно для сохранения целостности данных БД, то, как написал выше Andrey-MSK, это решается на стороне СУБД.
Если это локальная проверка на клиенте, то зачем здесь такие сложности с рефлексией, выражениями....
Всё решается гораздо проще.
1
 Аватар для XIST
1960 / 1061 / 148
Регистрация: 01.10.2009
Сообщений: 3,589
Записей в блоге: 1
28.03.2024, 21:42
SMEU, + за работу
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,173
31.03.2024, 18:09
Цитата Сообщение от SMEU Посмотреть сообщение
На само деле сам себе перемудрил.
Вот рабочий код, который вызывается через рефлексию
Если у вас бд EF(Entinty Framework) то вы перемудрили окончательно, в этой бд есть свои универсальные методы, чтобы реализовать CRUD при работе с этой бд рефлексия вообще не нужна. При работе с T классами проблем нет, всё доступно из под коробки
0
 Аватар для Andrey-MSK
3313 / 2200 / 387
Регистрация: 14.08.2018
Сообщений: 7,404
Записей в блоге: 4
01.04.2024, 08:37
Цитата Сообщение от xellan24rus Посмотреть сообщение
Если у вас бд EF(Entinty Framework)
EF это не БД, это ORM...
0
13 / 11 / 2
Регистрация: 03.12.2017
Сообщений: 22
02.04.2024, 10:56
А способ достать сущность через ChangeTracker не подойдёт?

C#
1
2
3
4
5
6
var noRemovableEntities= context.ChangeTracker
            .Entries<NoRemovableEntity>() 
            .Where(x=> x.Entity.Deleted == false && x.Id == 123) ///Сущности можно фильтровать по свойствам
            .Where(x=>x.State == EntityState.Deleted); ///Выберем сущности, которые пометили на удаление
 
return noRemovableEntities.Any();
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.04.2024, 10:56
Помогаю со студенческими работами здесь

Вызов метода через отражение (Reflection)
Допустим у меня есть приложение на c# со следующим кодом: using System; using System.Collections.Generic; using System.Linq; ...

Вызов метода хранимой процедуры через TabelAdapter
Такая проблема. Есть dataset В датасете есть TableAdapter для которого добавлена Хранимая процедура не возвращающая значение....

Использовать вызов конкретного метода через switch
Есть набор вызываемых реализованных методов db.createDataBase(); db.createTable(); db.insert(&quot;Name123&quot;, 25); ...

Полиморфизм: вызов метода базового класса, переопределенного метода и нового метода
В базовом классе метод помечен как virtual. Насколько я понял из книги: override означает, что метод не утрачивает связи с базовым...

Вызов метода через 3 сигнала
Добрый день. Вопрос такой. Есть 3 слота, которые принимают пакеты данных по readyRead. Далее считывают данные в глобальные QByteArray...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru