13726
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика Связь: @devmangx РКН: https://clck.ru/3FocB6
Визуализатор планов SQL-запросов для Entity Framework
Расширение EFCore.Visualizer для Visual Studio может стать настоящим прорывом.
Оно позволяет разработчикам просматривать план выполнения SQL-запросов напрямую внутри Visual Studio.
А ты уже пробовал? ☺️
👉 @KodBlog
5 недооценённых LINQ-методов, которые мгновенно улучшают твой код:
1. Zip — объединяет две последовательности в пары
2. Chunk — разбивает коллекцию на чанки фиксированного размера
3. OfType<T>() — фильтрует элементы по типу
4. DistinctBy — возвращает уникальные элементы по заданному ключу
5. SelectMany — разворачивает вложенные коллекции в плоский список
Бонус, который почти попал в топ:
> SequenceEqual — сравнивает две коллекции на равенство
> Aggregate — накапливает значение с помощью функции (reduce)
> GroupJoin — объединяет по группам (аналог LEFT OUTER JOIN)
> ToLookup — создает коллекцию, похожую на Dictionary, но с множеством значений
> Intersect — возвращает пересечение двух коллекций
LINQ — кладезь полезных методов, если знаешь, где копать 💪
👉 @KodBlog
Видишь баг?
9 из 10 разработчиков пропускают его. Проверь себя
Проблема:
> ExecuteUpdateAsync и ExecuteDeleteAsync обходят Change Tracker в EF Core
> Если SaveChangesAsync() потом упадёт — обновления в базе не откатятся автоматически
Решение:
✅ Явно оборачивай все такие команды в транзакцию вручную
Мелочь, а последствия могут быть серьёзные 😨
👉 @KodBlog
10 «секретных» ключевых слов в C#, которые используют синьоры, но не знают мидлы и джуны
Что это за ключевые слова? 👇
> extension
Новое ключевое слово в C# 14
Позволяет добавлять методы к уже существующим классам без изменения их исходного кода. Идеально подходит для чистого расширения поведения с новыми возможностями.
> await using
Вызывает IAsyncDisposable для асинхронного освобождения ресурсов.
> when (catch)
Фильтрует исключения в блоках catch на основе условий.
> partial
Разделяет определение класса на несколько файлов. Удобно для автогенерируемого кода или логической организации больших классов.
> readonly struct
Определяет неизменяемый тип значения (value type) с поведением сравнения по значению по умолчанию.
> in
Передаёт параметры по ссылке как только для чтения. Избегает лишнего копирования больших структур, повышая производительность без потери безопасности.
> extern
Указывает, что метод реализован вне текущего кода, как правило, в нативной библиотеке (DLL). Позволяет подключать неуправляемые библиотеки.
> volatile
Гарантирует, что значение поля всегда читается из основной памяти — важно в многопоточном коде. Помогает избегать тонких ошибок синхронизации.
> unsafe
Включает использование указателей и арифметику с ними, а также прямую работу с памятью.
> stackalloc
Выделяет память напрямую в стеке, а не в куче. Подходит для краткоживущих, высокопроизводительных сценариев.
👉 @KodBlog
EF Core: DbContextOptionsBuilder используется для настройки DbContext, как показано в примере для консольного проекта. Также он может применяться вместе с внедрением зависимостей (dependency injection)
👉 @KodBlog
В чём проблема с синглтоном (Singleton) в многопоточности?
Как реализовать потокобезопасный синглтон?
Две нити (потока) могут одновременно проверить, является ли экземпляр null, и обе получат true.
В результате каждая из них создаст собственный экземпляр, что нарушает основное правило паттерна Singleton — наличие только одного экземпляра.
Кроме того, экземпляр может быть уже создан до этой проверки, но другие потоки могут не увидеть его сразу, если не принять меры для обеспечения корректной видимости.
Как сделать реализацию потокобезопасной?
Один из распространённых способов — использование блокировки (locking), например, с применением double-check locking (двойной проверки).
Однако это сложный способ, и при неправильной реализации может привести к ошибкам.
Какое решение лучше?
На мой взгляд, универсального «лучшего» решения нет — всё зависит от конкретной ситуации. Мне нравится и я рекомендую использовать Lazy.
Вот как можно реализовать паттерн Singleton с использованием Lazy:
> Lazy Initialization: Класс Lazy автоматически управляет отложенной инициализацией экземпляра Singleton. Экземпляр создаётся только при первом обращении.
> Потокобезопасность: Lazy обеспечивает создание экземпляра в потокобезопасном режиме, поэтому нет необходимости использовать блокировки или double-check locking вручную.
> Простота и сопровождаемость: Код становится проще и легче поддерживать, так как вся логика синхронизации инкапсулирована внутри Lazy.
Такой подход рекомендуется в современной разработке на C#, поскольку он использует встроенные возможности .NET Framework для безопасной инициализации в многопоточной среде. 🙂
👉 @KodBlog
Rider 2025.2 EAP 4 уже тут
Этот билд приносит поддержку SQL-проектов базы данных через встроенный плагин — без доп. настройки:
> Шаблоны SQL-проектов в стиле SDK
> Сравнение схем и публикация проекта
> Импорт из БД, добавление ссылок и другое
Подробнее > jetbrains.com/rider/nextversion 🐸
👉 @KodBlog
Сократил время выполнения SQL-запроса с 70 мс до 1 мс.
Без изменений в коде. Без кэширования. Просто добавил filtered index (фильтрованный индекс).
Фильтрованные индексы — одна из самых недооценённых возможностей SQL.
Они позволяют индексировать только подмножество строк, соответствующих определённому условию — идеально подходят для флагов вроде ProcessedAt IS NULL.
Но есть нюанс: если условие выполняется для большинства строк, индекс не даст прироста производительности.
Эта оптимизация дала огромный прирост в одном из проектов.
В статье подробно разбирается реализацию и показывается, как это использовать: читать
👉 @KodBlog
MongoDB теперь нативно доступен на Azure.
Больше никаких "костылей" между сервисами.
Теперь можно:
> Запускать MongoDB Atlas напрямую из Azure Portal
> Интегрироваться с Azure AI, Databricks, OpenAI — в одном потоке
> Получать единый биллинг по всему стеку
Это будущее cloud-native разработки?
Или тесная интеграция с облаком — палка о двух концах для свободы разработчиков?
Полная разбивка: https://fnf.dev/4n1fsLd ✌️
👉 @KodBlog
Пример использования паттерна IOptions в ASP dotnet IOptions<T> обеспечивает безопасность на этапе компиляции и устраняет использование магических строк.
На втором примере эквивалент с использованием IConfiguration вместо IOptions
А ты используешь этот паттерн? 👀
👉 @KodBlog
Событийно-ориентированные фоновые задачи в C#
BackgroundWorker — это легковесный инструмент для выполнения асинхронной работы.
Обмен сообщениями между хостом и рабочим происходит через события.
Есть встроенная поддержка отмены задач и обновлений прогресса.
LINQPad визуализирует весь процесс :
вызвал Dump() — и данные сразу в окне Results как HTML.
Хочешь, стилизуй вывод с помощью CSS.
👉 Полный скрипт для загрузки доступен по ссылке: https://share.linqpad.net/phkul63s.linq
👉 @KodBlog
Самое раздражающее при отладке C#-кода?
(что может серьёзно замедлить процесс)
Проверка значений в коллекции.
Приходится разворачивать каждый элемент, чтобы посмотреть значения свойств.
Чтобы решить эту проблему, в Visual Studio недавно появилась функция закрепляемых свойств (pinnable properties).
Она позволяет быстро отслеживать нужные свойства.
Чтобы воспользоваться, наведите курсор на свойство и нажмите на иконку закрепления.
См. видео-пример, как это использовать 🕵️♀️
👉 @KodBlog
Visual Studio теперь отображает возвращаемые значения методов прямо в коде
Фича появилась в версии 17.12 (выпущена в ноябре).
Я всегда считал, что временные переменные помогают снизить когнитивную нагрузку при работе с возвратами методов, но, похоже, теперь игра изменилась
👉 @KodBlog
Понимание архитектуры микросервисов
Задумывались ли вы, как компании вроде Netflix и Amazon внедряют новые функции с молниеносной скоростью? Секрет может крыться в их технологическом стеке, основанном на микросервисной архитектуре.
В основе микросервисной архитектуры лежит идея разделения приложения на набор небольших, слабо связанных сервисов. Каждый сервис запускается как отдельный процесс, имеет чётко определённый API, располагается в своей кодовой базе, управляется отдельной командой и развёртывается независимо.
Ключевые компоненты микросервисной архитектуры:
1. Load Balancer (балансировщик нагрузки): равномерно распределяет входящий сетевой трафик между серверами.
2. CDN (Content Delivery Network): распределённая сеть серверов, доставляющая контент пользователю на основе его геолокации — ускоряет загрузку страниц.
3. API Gateway: маршрутизирует входящие запросы к нужному микросервису через REST API или другие протоколы.
4. Management (управление): отвечает за мониторинг и координацию микросервисов, обеспечивая их стабильную работу и взаимодействие.
5. Microservices (микросервисы): каждый сервис реализует отдельную функцию, может взаимодействовать с другими через RPC (удалённый вызов процедур) и сам отвечает за хранение данных или состояния.
Преимущества:
✅ Масштабируемость: можно масштабировать только нужные части приложения
✅ Гибкость: каждый микросервис разрабатывается, развёртывается и масштабируется независимо
✅ Устойчивость: сбой одного сервиса не выводит из строя всё приложение
✅ Быстрая доставка: небольшие кодовые базы — более быстрый выпуск новых функций
Недостатки:
❌ Сложность: больше сервисов — выше архитектурная сложность
❌ Согласованность данных: сложно поддерживать целостность данных между сервисами
❌ Сетевые задержки: взаимодействие между сервисами увеличивает время отклика
❌ Обработка ошибок: сложно отследить, где именно произошла ошибка
Микросервисная архитектура — не панацея, но мощный инструмент в арсенале современной разработки.
👉 @KodBlog
Как выполнить на 100% безопасную проверку с отрицанием условия?
Это проще, чем кажется.
Но в чём проблема со "старым" способом?
Оператор != может быть переопределён.
А это может привести к нежелательному поведению.
Зато с использованием отрицательного сопоставления с образцом (negated pattern matching) вы в безопасности.
Отрицательные шаблоны — это одна из новых возможностей, добавленных в C# за последние версии.
Они позволяют исключать определённые шаблоны с помощью ключевого слова not
Иными словами, можно исключать конкретные структуры из сопоставления.
С этим ваш код становится:
> Проще для понимания
> Читаемее
Но учтите:
Значение, к которому применяется выражение сопоставления, должно быть константным.
👉 @KodBlog
Вы правильно внедряете зависимости в контроллеры?
Многие разработчики об этом не знают 👇
В контроллер можно внедрить зависимости двумя способами:
↳ через конструктор
↳ через метод (endpoint)
Вы когда-нибудь работали с перегруженными контроллерами, в конструкторы которых передаётся слишком много зависимостей?
А вызываемый endpoint использует только часть из них.
❌ Это приводит к перерасходу памяти, так как все зависимости из конструктора выделяются в куче при каждом вызове контроллера — даже если они не используются.
✅ Так зачем не внедрять нужные объекты прямо в метод endpoint’а?
Для этого больше не требуется аннотация [FromServices] — как и в Minimal API.
Внедряя зависимости только там, где они реально нужны, вы повышаете читаемость, удобство поддержки и производительность контроллеров.
👉 @KodBlog
🌐 WAICORE — хостинг, за который не надо переживать
Устали от лагов, сложных панелей и переплат? Переходите на VPS с AMD Ryzen 9 — быстро, просто, без нервов.
💬 Почему клиенты выбирают нас:
— Цена начинается от 2€
— Скорость канала до 10 Гбит/с
— Поддержка 24/7 — отвечаем быстро и без шаблонов
☀Приятный бонус: Бесплатный VPN — расширение для браузера в подарок каждому нашему юзеру
VPN | Расширение для браузера
📍 Локации: Германия (Франкфурт), Москва, Нидерланды (уже скоро) — стабильный пинг, DDoS-защита.
🔥 Успейте сегодня
⤵ Выбрать сервер | 💬 Наш канал
Хочешь отслеживать изменения в базе данных в реальном времени?
Я реализовал Change Data Capture (CDC) в .NET с использованием Debezium, PostgreSQL и RabbitMQ.
Поток обработки:
> PostgreSQL настроен на генерацию событий об изменениях
> Debezium перехватывает эти изменения
> События публикуются в RabbitMQ
> MassTransit в .NET потребляет и обрабатывает их
Это лишь один из способов реализации архитектуры, основанной на событиях (Event-Driven Architecture).
Если ты проектируешь распределённые системы в .NET — вот полный гайд по созданию event-driven-систем с RabbitMQ ♟
👉 @KodBlog
Ставить точку или не ставить точку в сообщениях об исключениях? 👀
Байкшеддинг (bikeshedding) — большая проблема в нашей сфере.
Что такое "Bikeshedding"?
"Bikeshedding" — это феномен, также известный как закон тривиальности Паркинсона, при котором в организации несоразмерно много внимания уделяется незначительным вопросам. Это часто происходит на встречах: сложные темы быстро проходят без обсуждения (из-за нехватки знаний), а простые и понятные, вроде оформления сообщений об ошибках вызывают долгие споры.
Термин введён в книге Паркинсона "Law of Triviality". В ней описывается вымышленный комитет, обсуждающий проект ядерного реактора. Технические детали реактора одобряются без вопросов, никто не понимает их глубоко. А вот над проектом велосипедного сарая (bike shed) ведутся долгие дебаты: это всем понятно, каждый хочет высказаться.
Вот типичные примеры bikeshedding в разработке ПО — темы, на которые часто тратится непропорционально много времени, хотя они имеют минимальное влияние на результат:
Стиль кода и форматирование
> Tabs vs. spaces (табуляция или пробелы)
> Максимальная длина строки
> Расположение фигурных скобок {}
> Стиль комментариев и выравнивание docstring'ов
> Формат именования переменных (user_id vs userId)
Выборы в UI-дизайне
> Цвет кнопки или текст (“Отправить” vs “Отослать”)
> Пиксельная точность отступов
> Выбор иконки или шрифта
> Как открывать модалку — слайдом или затуханием
Структура проекта / имена файлов
> Где разместить папку utils
> Куда класть services — в Services/ или Domain/
> PascalCase vs kebab-case для файлов
Инструменты и конфигурация
> Что выбрать: ESLint или Prettier (или оба)
> Нужно ли требовать запятую в конце в массиве
> Какой task runner использовать: npm scripts или Gulp
Конвенции тестирования
> Формат имён тестов (*.test.js vs *.spec.js)
> Использовать Moq или NSubstitute
> Хранить тесты рядом с кодом или в папке tests/
Выбор зависимостей (при равной приемлемости)
> Axios или Fetch API
> EF Core или Dapper для CRUD
> Redux или Zustand в простом фронте
Технический педантизм
> Оверинжиниринг мелкой фичи "на будущее"
> Дебаты: функциональный подход или ООП в хелпере
> Внедрение шаблона проектирования там, где он не нужен
👉 @KodBlog
Внедрение настроек в .NET? Существует три основных интерфейса:
> IOptions: кэшируется на всё время жизни приложения
> IOptionsSnapshot: переоценивается при каждом запросе (scoped)
> IOptionsMonitor: позволяет получать текущее значение и реагировать на изменения
Используйте IOptions для статической конфигурации, IOptionsSnapshot — в веб-приложениях, где конфигурация может меняться между запросами, а IOptionsMonitor — когда нужно отслеживать изменения настроек.
Подробнее о том, как работает паттерн Options и когда какой интерфейс использовать: read
👉 @KodBlog
Улучшения производительности FrozenDictionary с целочисленными (int) ключами в .NET 10FrozenDictionary представляют собой коллекции, оптимизированные для чтения (Dictionary и Set), создание которых занимает больше времени, но чтение из них происходит быстрее по сравнению с неизменяемыми (immutable) коллекциями.
👉 @KodBlog
В EF Core 9 улучшена функция ExecuteUpdate
Небольшое, но полезное улучшение.
Эта возможность появилась в EF Core 8 — для производительного обновления данных в базе без загрузки в память.
Однако изначально она поддерживала только примитивные типы.
Если нужно было обновить комплексный тип, приходилось вручную перечислять все его свойства… до выхода EF Core 9.
Теперь комплексные типы полностью поддерживаются — больше не нужно делать это вручную 🙂
👉 @KodBlog
На небе и на земле только C# достоин почитания 😇
👉 @KodBlog
Записи действительно являются неизменяемыми.
Если вы знаете, как их определять.
Если запись объявлена традиционным способом, нет ограничений на использование обычного сеттера, что позволяет изменять объект после инициализации.
Однако, если в записи используется init только для части свойств, то такая запись не является полностью неизменяемой.
Так как же сделать их неизменяемыми?
Используйте позиционные записи.
Такой тип записей компилятор генерирует со свойствами только для инициализации (init-only).
Может показаться, что первый и второй вариант определения идентичны.
Но позвольте развеять это заблуждение.
Первая форма компилируется во вторую, и во втором случае вы можете заменить init на set и тем самым нарушить основную характеристику записей. 🐸
👉 @KodBlog
#1 ошибка, которую я вижу у .NET-разработчиков — это повсеместное использование null.
Ссылки на null стали причиной множества багов, уязвимостей и сбоев систем.
Вот 4 способа минимизировать использование null в C#:
1. Возвращайте пустое значение из метода
> если возможно, возвращайте пустой список вместо null
> например, используйте Enumerable.Empty<TResult>()
2. Исключайте null с помощью nullable reference types
> представлены в C# 8.0
> заставляют вас явно учитывать возможность null
3. Используйте паттерн Null Object
> объект, реализующий поведение “ничего не делать”
> позволяет избежать проверок на null
4. Используйте оператор null-условия (?.)
> безопасно обращается к свойствам объектов
> если экземпляр равен null, всё выражение вернёт null
Хотите сократить количество сбоев? Попробуйте эти подходы. 👀
👉 @KodBlog
Как сделать систему масштабируемой?
Современные приложения должны справляться с резкими всплесками трафика без сбоев.
Когда один сервер достигает предела, это чревато задержками, ошибками или полной недоступностью.
Есть два основных подхода:
> Вертикальное масштабирование → увеличение ресурсов одного сервера
> Горизонтальное масштабирование → добавление серверов за балансировщиком нагрузки
Для горизонтального масштабирования отличным выбором является YARP — высокопроизводительный обратный прокси от Microsoft для .NET.
В моих тестах с K6 масштабирование до 5 экземпляров API дало прирост:
✅ Время отклика: с 9.68 мс до 4.65 мс
✅ Пропускная способность: с 2260 RPS до 3881 RPS
Настроить YARP и запустить масштабирование можно за считанные минуты.
👉 Подробности: read
👉 @KodBlog
Как сделать настройки приложения строго типизированными?
Рекомендуемый способ — использовать паттерн Options.
Он обеспечивает строго типизированный доступ к конфигурации приложения.
В .NET паттерн Options реализован через три интерфейса:
> IOptions<T> — доступ к строго типизированным параметрам
> IOptionsSnapshot<T> — доступ к значениям конфигурации на момент запроса
> IOptionsMonitor<T> — доступ к текущим значениям и возможность подписки на изменения
Чтобы создать строго типизированную конфигурацию, можно использовать классы или record-типы.
❗️Нельзя использовать позиционные record-типы — нужен конструктор без параметров, обязательный для десериализации конфигурации.
Преимущества использования record-типов:
> Иммутабельность
> Читаемость
> Сравнение по значению (value equality)
Вы можете просто зарегистрировать тип в DI-контейнере и использовать его там, где нужно.
Реализация — простая, а преимущества очевидны:
> Строгая типизация конфигурации
> Разделение ответственности
> Централизация и согласованность
Этого достаточно, чтобы начать использовать подход в продакшн-проектах
👉 @KodBlog
Ты, скорее всего, пропустил это улучшение в LINQ
Теперь вместо того чтобы использовать Skip и Take для пропуска и выборки определённого количества элементов из коллекции, можно обойтись только Take.
Начиная с .NET 6, у метода Take появилась новая перегрузка, которая поддерживает ещё одну крутую фичу — диапазоны (Ranges).
А что такое диапазоны?
Они появились в C# 8 и позволяют брать подмножество коллекции с помощью оператора .., задавая начальный и конечный индексы.
Начальный индекс включается, конечный — нет. Оба индекса имеют тип Index.
Один из ключевых плюсов такого подхода — улучшенная производительность, так как под капотом процесс выборки данных может быть оптимизирован.
Но учти: если указать индекс, выходящий за пределы коллекции, будет выброшено исключение IndexOutOfRangeException
👉 @KodBlog
Какой язык более читаемый: C# или Python? Программисты забивают на безопасность?
Обсуждаем эти и другие холиварные темы в шоу Контура «Согласен — не согласен», где сталкиваются два представителя разных IT-профессий, каждый со своим мнением и бэкграундом.
Cмотрите самые горячие выпуски🔥
➡️ С# vs Python-разработчики: какой язык круче
➡️ Джун vs cеньор-разработчики: нужны ли джуны в бигтехе
➡️ Бэкендер vs фронтендер: кто больше страдает
➡️ Программист vs учитель информатики: делать ли программирование обязательным в школе
➡️ Безопасник vs программист: кто должен думать об уязвимости продукта
Новые дискуссии выходят в канале @KonturTech каждые две недели. Будет эмоционально, но с уважением.
16+. Реклама. АО «ПФ «СКБ Контур», ОГРН 1026605606620. 620144, Екатеринбург, ул. Народной Воли, 19А. Erid: 2SDnjcTtt77
Скриптинг на C# это круто 😎
Отлично подходит для простых POC и наполнения тестовыми данными, как в этом примере
👉 @KodBlog