C# Portal | Программирование
13.2K subscribers
1.41K photos
132 videos
31 files
1.07K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

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

Работаем с @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13❤3👎1🍾1
12 библиотек .NET, о которых стоит знать каждому разработчику

Сохраняйте подборку и делитесь с коллегами 🔖

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥5🍾1
Заказ сохранился, но так и не отправился

Приложение записывает заказ в БД, затем публикует событие для запуска доставки. Если брокер недоступен, а приложение остановится до повторной попытки, событие может потеряться.

Transactional Outbox помогает пережить такой сбой.
Заказ и событие сохраняются в одной транзакции БД: либо фиксируются обе записи, либо ни одна.

Фоновый обработчик читает таблицу outbox и отправляет события брокеру. Если отправка не удалась, запись остаётся для повторной попытки.

Но есть нюанс: обработчик может отправить событие и упасть до того, как отметит его отправленным. После перезапуска сообщение уйдёт повторно.

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

Проверьте оба сценария:

• Остановите брокер перед отправкой события.
• Остановите обработчик после отправки, но до обновления записи в outbox.

Разбор механизма и настройки в EF Core

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
Автоматическая регистрация зависимостей со Scrutor в ASP.NET Core

Scrutor расширяет встроенный DI-контейнер: сканирует сборки, находит сервисы и регистрирует их по заданным правилам.

Меньше ручных регистраций — особенно когда в проекте много однотипных сервисов.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🤨6👍2🍾2
Если сохранять данные в БД и публиковать сообщение двумя отдельными шагами, сбой между ними может привести к потере сообщения.

Outbox решает эту проблему: данные и сообщение сохраняются в одной транзакции, а фоновый обработчик позже отправляет сообщение брокеру.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾4❤2
Параллельное ожидание async-операций в .NET

Не ожидайте независимые асинхронные операции по очереди. Запустите их сразу, а затем дождитесь завершения через Task.WhenAll() — общее время не будет складываться из времени каждой операции.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾5
lock в C# не остановит второй экземпляр приложения

Когда приложение работает в нескольких экземплярах, каждый может запустить одну и ту же задачу по расписанию. У каждого процесса свой lock в памяти.

Для координации можно использовать advisory lock в PostgreSQL: оба экземпляра пытаются получить одну и ту же блокировку. Получивший запускает задачу, другой пропускает попытку.

Но есть нюансы:

• Сессионная блокировка удерживается соединением с БД. Если соединение потеряно, другой воркер может получить её, пока первый ещё выполняет работу.
• Блокировка не хранит историю выполненных запусков — их нужно учитывать отдельно.
• Повторное выполнение должно быть безопасным: блокировка сама по себе не гарантирует «ровно один раз».

Разбор и пример на C#

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾3
12 возможностей современного C#, которые стоит знать .NET-разработчику

C# заметно изменился: лаконичный синтаксис, средства работы с null, улучшения производительности и инструменты для конкурентного выполнения задач помогают писать более понятный и надёжный код.

Собрали 12 возможностей, которые пригодятся в повседневной разработке.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🍾1
Отдельная схема БД ещё не изолирует данные модуля

Если все модули используют одну учётную запись PostgreSQL, она может иметь доступ ко всем таблицам. Названия папок и схем этих прав не меняют.

Чтобы закрепить границы, каждому модулю можно выделить собственную роль с доступом только к его схеме и указать её в строке подключения. Тогда случайный запрос к приватной таблице другого модуля будет отклонён самой БД.

При этом каждому модулю по-прежнему нужны свой DbContext и явный контракт доступа к общим данным. Для совместного чтения владеющий модуль может предоставить API или представление (VIEW) с намеренно выданными правами.

Так границы модулей становятся проверяемым ограничением, а не просто договорённостью команды.

Практическое руководство: роли PostgreSQL, права доступа и настройка EF Core

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1🍾1
Singleton, Scoped и Transient в ASP.NET Core

Время жизни сервиса влияет на потребление памяти, состояние приложения и безопасность работы с несколькими потоками.

Singleton — один экземпляр на всё время работы контейнера DI. Подходит для общей конфигурации и потокобезопасных кэшей. Изменяемое состояние требует синхронизации, а зависимости должны быть рассчитаны на длительное использование.

Scoped — один экземпляр на scope, обычно на HTTP-запрос. Подходит для EF Core DbContext и состояния запроса. В фоновых сервисах scope нужно создавать явно.

Transient — новый экземпляр при каждом получении из DI. Подходит для лёгких независимых сервисов. Частое создание добавляет расходы на выделение памяти и инициализацию. Если такой объект сохраняется в Singleton, он остаётся жить вместе с ним.

Частая ошибка — внедрить Scoped-сервис в Singleton. Это может привести к некорректному разделению состояния и конфликтам при одновременных обращениях. Проверка scope помогает обнаружить такую зависимость.

Для выполнения операции создавайте отдельный scope через IServiceScopeFactory:
await using var scope = scopeFactory.CreateAsyncScope();

var service = scope.ServiceProvider
.GetRequiredService<IMyScopedService>();

await service.ProcessAsync();


Для работы с БД внутри BackgroundService можно использовать такой scope или IDbContextFactory<TContext>:
await using var db =
await dbContextFactory.CreateDbContextAsync();

var orders = await db.Orders.ToListAsync();


DbContext
не потокобезопасен. Scoped определяет время жизни, но не защищает от конкурентного доступа. Для параллельных операций используйте отдельные экземпляры контекста.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🍾2
Два запроса — одна квартира — двойное бронирование

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

Один из способов защиты — оптимистическая конкуренция через общую строку квартиры. При создании бронирования каждый запрос также обновляет эту строку в одной транзакции. У неё есть токен версии, который меняется при обновлении.

EF Core добавляет прочитанную версию в условие UPDATE. Первый запрос успешно сохраняет изменения. Второй использует уже устаревшую версию и получает DbUpdateConcurrencyException; его транзакция откатывается.

После конфликта нельзя просто повторить запись. Нужно заново прочитать актуальные данные и проверить доступность дат.

Версия только на новой строке бронирования здесь не поможет: запросы создают разные строки и не конфликтуют между собой.

Разбор и пример на EF Core

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🍾1
Сны вайб-кодеров 🐺

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17😁7🍾1
«Запрос использует индекс» — это ещё не значит, что с производительностью всё в порядке.

Допустим, нужно получить последний комментарий к задаче. Индекс отсортирован сначала по ID задачи, затем по ID пользователя и только потом по дате. Он позволяет найти комментарии к нужной задаче, но внутри они сгруппированы по пользователям, а уже затем отсортированы по дате. Это не тот порядок, который нужен запросу, поэтому базе данных всё равно может потребоваться дополнительная сортировка.

В запросе для дашборда такая работа может повторяться для каждой задачи.

План выполнения запроса помогает проверить условия фильтрации, порядок сортировки и количество циклов выполнения. Для такого запроса лучше подойдёт индекс по ID задачи и дате.

Но даже в этом случае нужно измерять производительность всего запроса. Дополнительные индексы занимают место и увеличивают нагрузку при записи данных.

В примере с PostgreSQL показано, как порядок столбцов в индексе влияет на план выполнения.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🍾2🔥1
Rate Limiting в ASP.NET Core: одного middleware недостаточно

Ограничение частоты запросов помогает защитить API от перебора паролей, злоупотребления запросами, резких скачков трафика и чрезмерного потребления ресурсов.

Но полагаться только на middleware внутри приложения — ошибка. Защищать нужно всю цепочку обработки запросов:

CDN и защита от DDoS → WAF → API Gateway → .NET API → внутренние сервисы

Каждый уровень решает свои задачи: от фильтрации вредоносного трафика до ограничения нагрузки на приложение и зависимые сервисы.

Надёжная защита API — это не одна настройка, а многоуровневый подход.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🍾1
Таймаут в ASP.NET Core не гарантирует остановку выполнения

Middleware для ограничения времени выполнения в ASP.NET Core отменяет токен отмены (CancellationToken), но не останавливает поток принудительно и не заставляет endpoint немедленно вернуть ответ.

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

В примере из статьи для endpoint установлен лимит в 3 секунды. Но если внутри него выполняется десятисекундная задержка, которая игнорирует токен отмены, обработка может продолжиться и завершиться ответом 200 OK.

Проверить поведение можно в двух сценариях: когда операция корректно реагирует на отмену и когда игнорирует её. Тестировать нужно без подключённого отладчика — в описанном примере таймаут не срабатывает под отладчиком.

Разбор настройки таймаутов и обработки отмены в ASP.NET Core

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🍾1
7 архитектур .NET, которые должен знать каждый разработчик в 2026 году

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

Разберём основные архитектурные подходы и случаи, когда их стоит использовать.

Монолитная архитектура (Monolithic Architecture). Подходит для небольших приложений, MVP и проектов с простой предметной областью. Такие приложения быстро разрабатывать, но их масштабирование со временем может стать сложнее.

Многоуровневая архитектура (N-Tier Architecture). Классический подход с чётким разделением ответственности между уровнями. Идеально подходит для корпоративных приложений, хотя компоненты всё ещё могут оставаться тесно связанными.

Чистая архитектура (Clean Architecture). Предполагает независимость бизнес-логики от фреймворков и пользовательского интерфейса. Отлично подходит для систем, которые должны оставаться удобными в поддержке и тестировании в долгосрочной перспективе.

Архитектура вертикальных срезов (Vertical Slice Architecture). Организует код по функциональным возможностям, а не по слоям. Хорошо подходит для гибких команд и позволяет быстрее разрабатывать новые функции.

Микросервисная архитектура (Microservices Architecture). Подходит для крупных систем, которым необходимы независимое развёртывание компонентов и высокая масштабируемость. Однако такой подход усложняет эксплуатацию и поддержку инфраструктуры.

CQRS (Command Query Responsibility Segregation). Разделяет операции чтения и записи данных. Особенно полезен для высоконагруженных систем и приложений со сложной бизнес-логикой.

Событийно-ориентированная архитектура (Event-Driven Architecture). Обеспечивает слабую связанность компонентов и обработку событий в реальном времени. Подходит для распределённых систем и интеграции различных сервисов.

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

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🍾1
Обрати внимание, где именно расположен ToList() в этом посте про Entity Framework, который я сегодня увидел в LinkedIn.

СПОЙЛЕР: Оба варианта генерируют практически одинаковый SQL-запрос (за исключением того, что в правом варианте столбец City не выбирается).

Однако мне больше нравится правый вариант, где
Where стоит перед Select, — с точки зрения стиля и читаемости кода.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
1👎6❤‍🔥3🍾3👍2
Clean Architecture нужна не каждому .NET-проекту

При разработке на ASP.NET Core легко увлечься архитектурой и создать несколько слоёв абстракций даже для простых функций. Но иногда Vertical Slice Architecture (VSA) позволяет писать код проще и быстрее.

Вместо разделения приложения на слои VSA группирует код по функциям и сценариям: например, CreateOrder, GetOrder и CancelOrder. Внутри каждого слайса находятся необходимые обработчики, валидация, модели запросов и ответов.

В чём преимущества VSA?

— Меньше лишних абстракций и шаблонного кода.
— Изменения одной функции реже затрагивают остальные.
— Проще ориентироваться в коде и добавлять новые возможности.
— Не нужно создавать интерфейс и репозиторий для каждой операции, если они не приносят реальной пользы.

Это не значит, что Clean Architecture устарела. Она по-прежнему отлично подходит проектам со сложной бизнес-логикой и строгими архитектурными границами.

Практичный подход — начать с Vertical Slice Architecture и добавлять слои и абстракции по мере необходимости. При этом важно следить, чтобы логика не дублировалась между слайсами.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍8🍾1
Кто я такой, чтобы спорить 🦀

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍6😁5👎1🍾1
HTTPS-редиректа недостаточно для защиты приложения ASP.NET Core

Многие разработчики включают UseHttpsRedirection() и считают, что приложение защищено. Но есть ещё один важный механизм безопасности, о котором не стоит забывать, — HTTP Strict Transport Security (HSTS).

Разберёмся, как они работают вместе.

1. HTTPS-редирект: UseHttpsRedirection()
Автоматически перенаправляет входящие HTTP-запросы на HTTPS. Например: http://example.com → https://example.com

Однако первый HTTP-запрос всё ещё может передаваться по незащищённому соединению до выполнения перенаправления.

2. HSTS: UseHsts(). HSTS указывает браузеру использовать для домена только HTTPS. Получив заголовок HSTS по защищённому соединению, браузер:

• Автоматически переключает последующие HTTP-запросы на HTTPS.
• Не позволяет пользователю обойти предупреждение о недействительном сертификате.
• Помогает защититься от атак, связанных с понижением версии протокола.

3. Настройка обоих механизмов в ASP.NET Core

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHsts(options =>
{
options.MaxAge = TimeSpan.FromDays(365);
options.IncludeSubDomains = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
app.UseHsts();
}

app.UseHttpsRedirection();

app.MapGet("/", () => "Secure API");

app.Run();


Здесь HSTS действует в течение одного года, а директива IncludeSubDomains распространяет его действие на поддомены.

Важно: включайте IncludeSubDomains, только если все поддомены поддерживают HTTPS.

4. Что учитывать в production

• Обратные прокси. Если используются AWS ALB, Nginx или другой reverse proxy, завершение HTTPS-соединения и перенаправление могут выполняться на уровне инфраструктуры.

• Forwarded-заголовки. При необходимости настройте UseForwardedHeaders() для доверенных прокси до UseHttpsRedirection(). Иначе приложение может неправильно определять схему запроса и создавать циклы перенаправлений.

• Web API. HSTS применяется преимущественно браузерами. Для API, которыми пользуются мобильные приложения и другие клиенты, необходимо обеспечивать HTTPS на уровне сервера или инфраструктуры, а не полагаться на редиректы.

• HSTS Preload. Рассматривайте предварительное включение домена в список HSTS только тогда, когда весь домен и все его поддомены постоянно готовы работать через HTTPS.

Рекомендация: обеспечивайте принудительное использование HTTPS на границе инфраструктуры, а для приложений, доступных через браузер, дополнительно используйте HSTS. Важно, чтобы оба механизма были настроены согласованно.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤2🍾1
10 причин, почему macOS лучше Windows для .NET-разработчиков

Visual Studio работает только на Windows. И всё же для большинства .NET-разработчиков macOS может оказаться более удобной рабочей машиной.

Автор больше 13 лет разрабатывает приложения на .NET и на Windows, и на Mac. Вот его сравнение обеих платформ. 10 причин выбрать macOS

1. Unix-подобная система. Пути к файлам, права доступа и shell-скрипты работают ближе к тому, как они устроены на Linux-серверах и в контейнерах, куда вы деплоите приложения.

2. Более удобная работа с Docker. Linux-контейнеры запускаются без типичных проблем WSL, таких как чрезмерное потребление памяти, сетевые сбои и проблемы с синхронизацией файлов.

3. Производительность Apple Silicon. .NET работает нативно на ARM64. Чипы серии M быстро собирают большие проекты и при этом почти не шумят.

4. Автономность на весь день. Можно компилировать код, отлаживать приложения и запускать контейнеры в течение рабочего дня без зарядки.

5. Отличные IDE. JetBrains Rider и VS Code с ReSharper или C# Dev Kit работают на macOS нативно и предоставляют полноценные возможности для разработки.

6. Homebrew. Одна команда позволяет установить .NET SDK, Node.js, базы данных и CLI-инструменты, а затем обновлять их.

7. Качество оборудования. Чёткий экран, удобный трекпад и корректно работающий спящий режим.

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

9. Чистая система. Меньше предустановленного ПО и никакой рекламы в системном интерфейсе.

10. Все цели для .NET MAUI на одном устройстве. Для сборки и подписания приложений под iOS и macOS нужен Mac. На нём можно разрабатывать приложения для Android, iOS и macOS в одном окружении.

5 причин выбрать Windows

1. Полноценная Visual Studio. Расширенные инструменты отладки, визуальные дизайнеры и профилировщики. Visual Studio for Mac закрыли в 2024 году. Если вы привыкли к Visual Studio и не хотите переходить на Rider или VS Code, Windows остаётся основным вариантом.

2. Разработка десктопных приложений. WPF, Windows Forms и WinUI предназначены для Windows и требуют Windows для полноценного запуска и отладки.

3. Старые проекты на .NET Framework. Устаревшие приложения на .NET Framework и ASP.NET могут требовать Windows, особенно если используют специфичные для этой платформы технологии.

4. SQL Server и SSMS. Оба инструмента нативно работают на Windows. На Mac SQL Server можно запустить в Docker, а SQL Server Management Studio (SSMS) не поддерживается нативно.

5. Цена и выбор оборудования. Больше производителей, возможность самостоятельно обновлять оперативную память и накопители, а также более высокая производительность за те же деньги у многих конфигураций.

Большинство новых .NET-приложений работают в Linux-контейнерах. Поэтому Unix-подобная система на ноутбуке может быть ближе к продакшен-окружению, чем Windows.

→ macOS — веб-разработка, облачные сервисы и мобильные приложения.

→ Windows — десктопные приложения и поддержка старых проектов на .NET Framework.

А на чём вы разрабатываете на .NET: macOS, Windows или Linux?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
1🥴13❤3😁1🌚1🍾1