C# Portal | Программирование
13.9K subscribers
1.15K photos
126 videos
29 files
926 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

Сотрудничество, реклама: @devmangx

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
Пример итерации по словарю с деконструкцией KeyValuePair с осмысленными именами переменных вместо использования Key/Value, что делает код более читаемым.

#dotnet #csharp

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11🤔4
Вашему .NET-приложению не обязательно быть медленным в 2026 году.

Кэширование — один из самых простых способов повысить производительность, и IMemoryCache — самый простой вариант, с которого можно начать:

- Очень быстрый
- Простой в использовании
- Не требует внешних зависимостей

Но есть компромиссы:

- Данные теряются при перезапуске
- Ограничено памятью одного сервера

Нужно более надёжное или масштабируемое решение?

Вот гайд по вариантам распределённого кэширования в .NET:

P.S. Не забывайте, что кэширование не решает корневую проблему производительности. Поэтому обязательно сначала проанализируйте и устраните её.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳2🍾21👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Docker за 2 минуты

Большинство разработчиков используют Docker каждый день, не понимая, что происходит под капотом. Вот всё, что нужно знать.

У Docker есть 3 основных компонента:

1. Docker Client: место, где ты вводишь команды, которые через API общаются с Docker daemon.

2. Docker Host: здесь работает daemon, который делает всю основную работу (сборка образов, запуск контейнеров и управление ресурсами)

3. Docker Registry: хранилище Docker-образов. Docker Hub — публичный, но компании часто поднимают приватные registry.

Вот что происходит, когда ты запускаешь docker run:

• Docker подтягивает образ из registry (если его нет локально)
• Docker создаёт новый контейнер из этого образа
• Docker выделяет контейнеру файловую систему с возможностью записи (read-write)
• Docker создаёт сетевой интерфейс для подключения контейнера
• Docker запускает контейнер

Вот и всё.

Client, host и registry могут находиться на разных машинах. Именно поэтому Docker хорошо масштабируется.

Понимание этой архитектуры сильно упрощает дебаг контейнеров — ты точно знаешь, где искать проблему, если что-то ломается.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🕊2
Я годами использовал WebApplicationFactory и TestContainers.

Потом попробовал тестирование в .NET Aspire — и назад не вернусь.

Вот почему: тесты через WebApplicationFactory проверяют API в изоляции.
Остальные сервисы ты мокируешь.

Это значит, что ты никогда не ловишь баги, которые возникают при взаимодействии сервисов A и B в проде.

Традиционный сетап выглядит так:

→ Прямая ссылка на проект API
→ Ручной подъём Docker-контейнеров через TestContainers
→ Переопределение connection string через переменные окружения
→ Мок внешних сервисов, от которых зависит API
→ Надежда, что в проде всё будет работать вместе

Слишком много glue-кода ради одного теста.

.NET Aspire поднимает ВСЮ распределённую систему в рамках одного теста:
→ Все API запущены
→ Реальные контейнеры PostgreSQL и Redis
→ Реальные HTTP-вызовы между сервисами
→ Ноль моков

Вот 3 конкретных плюса, которые я получил сразу:

𝟭. Больше нет boilerplate с TestContainers

Раньше: 50+ строк на конфигурацию PostgreSQL-контейнера, connection string и переменных окружения.

Теперь: одна строка — ссылка на AppHost.
Aspire делает всё сам.

𝟮. Тесты поймали ломающее изменение API-контракта

Products API изменил модель ответа.
С моками тесты всё ещё проходили.

С Aspire — Stocks API сразу упал, потому что не смог десериализовать ответ. Поймали до продакшена.

𝟯. Порядок старта сервисов автоматический

Больше нет случайных падений тестов из-за того, что API стартовал раньше, чем PostgreSQL был готов. Aspire автоматически ждёт зависимости.

Завтра я отправлю полный гайд для 25,149+ .NET-разработчиков:

- Точный сетап DistributedApplicationTestingBuilder, который я использую
- Как шарить один инстанс приложения на 100+ тестов (сильный буст скорости)
- Моя стратегия очистки базы, которая предотвращает «загрязнение» тестов
- 2 продвинутых паттерна: тестирование фоновых задач и очередей сообщений

Это тот подход к тестированию, который наконец сделал распределённые системы тестируемыми.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍5🕊2
5 Архитектурных Тестов Необходимых Каждому .NET-Проекту.

Каждый проект начинается с благих намерений. Вы согласовываете границы слоёв, соглашения об именовании, направление зависимостей. Через полгода кто-то переносит доменный сервис в проект инфраструктуры, обработчик получает имя не по соглашению или внутренний класс становится публичным, потому что это значение по умолчанию. Архитектурные тесты предотвращают это. Они превращают архитектурные правила в автоматизированные тесты, которые запускаются в CI. Вот архитектурные тесты, которые пригодятся каждому проекту.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
1👏1
Перестань дублировать JOINы — используй USING

Если ты давно пишешь SQL-запросы, ты, скорее всего, привык к ON. Он работает. Но когда ты джоинишь две таблицы по колонкам с одинаковыми именами, есть более чистый и элегантный способ — USING.

Вот почему стоит на него перейти.

SELECT 
e.Employee_ID,
e.Employee_Name,
e.Department,
s.Net_Sales
FROM Employees e
JOIN sales s
ON e.Employee_ID = s.Employee_ID


ON работает, но он многословный. Приходится повторять имена таблиц и колонок. Если имя колонки одинаковое в обеих таблицах, ты фактически пишешь одно и то же дважды. Хуже того, при выборке ты получишь два столбца Employee_ID, если явно их не квалифицировать.

USING — это сокращённая форма для JOIN по равенству колонок с одинаковыми именами. Тот же запрос:

SELECT 
e.Employee_ID,
e.Employee_Name,
e.Department,
s.Net_Sales
FROM Employees e
JOIN sales s
USING (Employee_ID);


Гораздо чище, правда? USING автоматически сопоставляет колонки с одинаковым именем и выполняет INNER JOIN (или LEFT/RIGHT JOIN — в зависимости от типа соединения). Ты указываешь имя колонки только один раз.

Использование USING — небольшое изменение, которое делает SQL более лаконичным и самодокументируемым. Это снижает вероятность ошибок и делает результирующие наборы данных чище.

Убедись, что твоя СУБД поддерживает USING.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
13👎3😁1
Agent Framework: фоновые ответы решают проблему таймаутов у долгоживущих агентов

Агенты, использующие reasoning-модели, могут выполнять задачу несколько минут — глубокое исследование, многошаговый анализ, генерация объёмного контента. Держать HTTP-соединение открытым всё это время ненадёжно: балансировщики нагрузки рвут соединение по таймауту, мобильные клиенты отваливаются, и любая ошибка приводит к потере всего накопленного прогресса.

Фоновые ответы в Microsoft Agent Framework позволяют вынести такие долгие операции в background, чтобы приложение оставалось отзывчивым и устойчивым независимо от того, сколько времени агенту нужно на выполнение задачи.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👏1
Улучшения в EF Core 11 Preview 2 для SQL Server

▪️Поддержка операторов MaxBy() и MinBy() в LINQ-запросах.

▪️Интеграция с векторными индексами SQL Server DiskANN и новой функцией VECTOR_SEARCH(), что позволяет реализовать высокопроизводительный поиск по векторному сходству.

▪️Создание полнотекстовых каталогов и индексов SQL Server напрямую из EF Core.
Поддержка функций полнотекстового поиска FREETEXTTABLE() и CONTAINSTABLE().

▪️Поддержка JSON_CONTAINS() для упрощения запросов к JSON-данным, хранящимся в SQL Server.

EF Core 11 требует .NET 11 SDK.

https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-11.0/whatsnew

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾1
Секрет: как устранить 99% NullReferenceException

Немногие разработчики об этом знают.

Но это может полностью изменить то, как вы пишете код на C#.

NullReferenceException — самая частая runtime-ошибка в проектах на .NET.

И обычно она возникает в самый неподходящий момент — уже в продакшене.

Большинство разработчиков исправляют NullReferenceException постфактум.

Опытные — предотвращают их появление заранее.

Почти все такие ошибки можно убрать с помощью двух простых настроек проекта.

Добавьте это в ваш .csproj:

<PropertyGroup>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>


Как это работает:

Nullable включает статический анализ null-ссылок в C#:
↳ предупреждает о потенциальных null-проблемах
↳ заставляет явно обрабатывать nullable-типы
↳ делает работу с null явной в коде

TreatWarningsAsErrors превращает предупреждения в ошибки сборки:
↳ проект не скомпилируется, пока не исправлены null-проблемы (и другие warnings)
↳ ошибки ловятся на этапе разработки, а не в продакшене

Совет:

Можно добавить эти настройки в файл Directory.Build.props (рядом с .sln) — тогда они применятся ко всем проектам в решении.

Вместе эти настройки смещают проблемы с null
с runtime → на этап компиляции.

Так и устраняется 99% NullReferenceException в проектах.

Это одна из самых «выгодных» настроек в .NET по соотношению эффект/затраты.

В следующий раз при создании проекта — начните именно с этого.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🥴74🤔2
SSO — это процесс аутентификации, который позволяет пользователям получать доступ к нескольким приложениям с помощью одного основного ключа.

Это реализуется с использованием централизованного сервера аутентификации, который хранит учётные данные пользователя и проверяет их для каждого приложения.

Вот какие шаги происходят, если вы хотите войти в веб-приложение Trello, используя аккаунт Google:

1. Открываете страницу входа Trello и выбираете Google как способ авторизации
2. Trello перенаправляет пользователя на страницу входа Google
3. Пользователю отображается страница входа Google
4. Пользователь вводит свои учётные данные Google
5. Google отправляет информацию аутентификации на сервер авторизации SSO
6. Если учётные данные валидны, сервер авторизации возвращает токен аутентификации (SAML)
7. Google отправляет токен аутентификации в Trello
8. На последнем шаге Trello отправляет токен на сервер аутентификации Google для его валидации
9. Если токен валиден, Trello предоставляет пользователю доступ и сохраняет сессию для последующих взаимодействий

Преимущества SSO:

- Улучшенный пользовательский опыт. Пользователю не нужно запоминать несколько логинов и паролей.
- Повышенная безопасность. Пользователи реже переиспользуют пароли в разных приложениях.

Недостатки:

- Единая точка отказа. Один из ключевых минусов — SSO создаёт single point of failure. Если система SSO скомпрометирована, злоумышленник может получить доступ ко всем подключённым приложениям и сервисам.
- Риски безопасности. Если учётные данные скомпрометированы, под угрозой оказываются все связанные приложения.

Некоторые распространённые типы SSO:

- SAML-based SSO. Самый распространённый тип SSO. Использует протокол SAML для обмена данными аутентификации между SSO-сервером и приложениями.
- OpenID Connect. Более новый тип SSO, основанный на OAuth 2.0. Проще по сравнению с SAML и легче интегрируется с веб-приложениями.

И популярные решения SSO:

- Azure Active Directory
- Okta
- Ping Identity
- OneLogin
- Google Cloud Identity Platform

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
7👏2🥴1
This media is not supported in your browser
VIEW IN TELEGRAM
Кто-то сделал веб-симулятор System Design.

Называется Paperdraw. Он позволяет перетаскивать компоненты (drag & drop) и в реальном времени смотреть, как они ведут себя при реальных условиях: нагрузке, сбоях, задержках и масштабировании.

100% бесплатно можно попробовать.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥4👍3👏1
10 скрытых фич EF Core, которые используют сеньоры

1️⃣Shadow Properties
EF Core позволяет добавлять свойства, которых нет в классе, но которые присутствуют в базе данных.
Идеально подходят, например, для хранения данных аудита, не засоряя сущности лишними полями.

2️⃣Query Tags
Можно легко добавлять комментарии к SQL-запросам, которые генерирует EF Core.
Удобно при профилировании - в логах SQL сразу видно, откуда пришёл тот или иной медленный запрос.

3️⃣Compiled Queries
Часто используемые запросы можно скомпилировать заранее, чтобы не тратить ресурсы на парсинг каждый раз.
Повышает производительность при большом числе однотипных запросов.

4️⃣DbContext Pooling
Вместо того чтобы каждый раз создавать новый DbContext, можно переиспользовать уже созданные.
Существенно снижает потребление памяти и повышает производительность.

5️⃣Value Converters
Позволяют автоматически преобразовывать значения между .NET и базой данных.
Полезно для хранения кастомных типов, enum'ов и Value Object'ов.

6️⃣Temporal Tables
Позволяют отслеживать историю изменений данных прямо в базе.
Удобно для аудита, отката изменений и анализа исторических данных.

7️⃣Database Seeding
EF Core 9 добавил новые методы UseSeeding, UseAsyncSeeding для удобного наполнения базы начальными данными.

8️⃣Split Queries for Includes
Позволяет разбивать сложные запросы с Include на несколько простых.
Избегает проблем с громоздкими JOIN’ами и повышает производительность.

9️⃣Raw SQL Queries
Можно выполнять чистый SQL прямо из EF Core.
Полезно, когда нужно выжать максимум производительности или использовать специфичный функционал конкретной СУБД.

1️⃣0️⃣Миграции для нескольких баз данных
Можно легко управлять миграциями и схемами сразу для разных провайдеров.
Подходит для приложений, которые должны работать с несколькими СУБД (например, SQL Server, PostgreSQL, MySQL).

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾43🥴1
EF Core 9 наконец упрощает сидинг данных.

С UseSeeding и UseAsyncSeeding теперь можно загружать начальные данные прямо из DbContext.

Меньше ручного кода и гораздо более чистая настройка.

Вот код с изображения:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SeedingEfCore")
.UseAsyncSeeding(async (context, _, cancellationToken) =>
{
if (!await context.Set<Category>().AnyAsync(cancellationToken))
{
await context.Set<Category>().AddRangeAsync(
new Category { Name = "Backend" },
cancellationToken
);

await context.SaveChangesAsync(cancellationToken);
}
});
}


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾1
C# 15 добавляет union-типы: закрытые наборы вариантов (case types), исчерпывающее pattern matching, неявные преобразования и даже поддержку кастомных union-типов без boxing.

Это серьёзное улучшение удобства для API, которые возвращают «один из нескольких вариантов».

Полный пост: https://devblogs.microsoft.com/dotnet/csharp-15-union-types/

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🍾52🔥1
Выпущен JavaScript-движок Okojo для .NET.

В бенчмарках он более чем в 3 раза быстрее, чем Jint, при этом с низкими аллокациями!

В комплекте расширения: встраивание Wasm, reflection, генерация биндингов с d.ts, runtime, совместимый с Node, отладчик VSCode и многое другое.

За исключением некоторых частей (прямой eval / with и т.д.), базовая реализация проходит test262 почти на 100%!

На данный момент поддерживается только .NET 10.

https://github.com/akeit0/okojo

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🍾21
В .NET 10 формат .slnx стал дефолтным не просто так. Старый формат .sln был разработан в начале 2000-х, когда Visual Studio была единственным инструментом. Он никогда не предназначался для работы с Git.

35 строк с GUID’ами для 3 проектов? Конфликты при мердже каждый раз, когда кто-то добавляет проект? Проприетарный формат, который нельзя валидировать стандартными инструментами?

Формат .slnx решает всё это. 7 строк чистого XML. Без GUID’ов. Git автоматически мерджит добавления проектов. Поддерживается всеми IDE.

«Но у меня уже есть проекты…»

Одна команда: dotnet sln migrate

И всё. Старый .sln остаётся нетронутым, пока ты не проверишь результат. Риск буквально нулевой.

Реальный риск — продолжать использовать старый формат и идти против экосистемы, которая движется вперёд.

Согласен или нет?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥36👍5💯21🍾1
Aspire 13.2 тихо завёз суперсилу: теперь твой терминал может читать документацию за тебя.

aspire docs list        → всё
aspire docs search redis → результаты с ранжированием по релевантности
aspire docs get <slug> → полная страница, без браузера


https://buff.ly/RFUftBI

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🍾1
Мы Создали Слой Кэша. PostgreSQL Показал, что Зря.

Пользователь открывает страницу свего тарифного плана, а видит старый. Он обновляет страницу, и всё исправляется. Наш показатель попадания в кэш 98%, а мы всё равно выглядели некомпетентными. В тот момент мы перестали рассматривать кэширование как функцию повышения производительности и стали рассматривать его как проблему истинности. Потому что система перестала быть медленной, зато она стала ненадёжной.

Что было дальше 🤙

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4👍2🍾2👎1
DataAnnotations против FluentValidation

1️⃣DataAnnotations тоже позволяют валидировать данные с проверкой в базе через кастомный атрибут + IUserRepository.

2️⃣Но когда правило разрастается, FluentValidation обычно оказывается чище, слабее связан с остальным кодом и проще покрывается тестами.

#dotnet #csharp

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🍾1
Хватит жонглировать разрозненными инструментами для JSON. 🧱

JSON-everything — это высокопроизводительный, соответствующий стандартам набор инструментов для Schema, Patch, Path и других задач — всё в рамках одной экосистемы .NET. Открытый исходный код, ориентирован на современные сценарии разработки.

https://hubs.li/Q04bsKZy0

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
4🍾1
Забирай мой подход для упрощения управления потоками:

(начиная с .NET 9)

Вместо классического System.Threading.Monitor в .NET 9 появился новый тип — System.Threading.Lock.

Вместе с ним появился метод Lock.EnterScope(), который создаёт эксклюзивную область и автоматически освобождает блокировку после выхода из блока кода.

Этот тип даёт более удобную синхронизацию потоков через свой API.

Оператор lock в C# умеет распознавать, когда целью блокировки выступает объект Lock.

В таком случае он использует новый API, а не классический механизм.

Смотри код ниже.

Что думаешь про это нововведение?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍4🤣32👎1