C# Portal | Программирование
C# Portal | Программирование
Хотите стать успешным C#-разработчиком? Присоединяйтесь к нашему информативному Telegram-каналу. Здесь вы найдёте полезные советы, статьи и руководства по разработке на C#. Развивайтесь в профессии и следите за новостями мира IT.
Присоединяйтесь к нашему сообществу уже сегодня!
Публикации канала
GitHub ускоряет запись данных в репозитории в 3–4 раза GitHub меняет механизм блокировок в Spokes: вместо одной блокировки на весь репозиторий будут использоваться отдельные блокировки для каждой ссылки на Git-объект (ref). Это позволит обновлять разные refs параллельно, не блокируя друг друга, даже при межрегиональных задержках около 25 мс. По результатам внутренних тестов GitHub, новый подход увеличил пропускную способность операций записи в 3–4 раза. Главная идея — меньше лишних блокировок и больше параллелизма при работе с репозиториями. 👉 @KodBlog
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
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
Кто я такой, чтобы спорить 🦀 👉 @KodBlog
Clean Architecture нужна не каждому .NET-проекту При разработке на ASP.NET Core легко увлечься архитектурой и создать несколько слоёв абстракций даже для простых функций. Но иногда Vertical Slice Architecture (VSA) позволяет писать код проще и быстрее. Вместо разделения приложения на слои VSA группирует код по функциям и сценариям: например, CreateOrder, GetOrder и CancelOrder. Внутри каждого слайса находятся необходимые обработчики, валидация, модели запросов и ответов. В чём преимущества VSA? — Меньше лишних абстракций и шаблонного кода. — Изменения одной функции реже затрагивают остальные. — Проще ориентироваться в коде и добавлять новые возможности. — Не нужно создавать интерфейс и репозиторий для каждой операции, если они не приносят реальной пользы. Это не значит, что Clean Architecture устарела. Она по-прежнему отлично подходит проектам со сложной бизнес-логикой и строгими архитектурными границами. Практичный подход — начать с Vertical Slice Architecture и добавлять слои и абстракции по мере необходимости. При этом важно следить, чтобы логика не дублировалась между слайсами. 👉 @KodBlog
Обрати внимание, где именно расположен ToList() в этом посте про Entity Framework, который я сегодня увидел в LinkedIn. СПОЙЛЕР: Оба варианта генерируют практически одинаковый SQL-запрос (за исключением того, что в правом варианте столбец City не выбирается). Однако мне больше нравится правый вариант, где Where стоит перед Select, — с точки зрения стиля и читаемости кода. 👉 @KodBlog
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
Таймаут в ASP.NET Core не гарантирует остановку выполнения Middleware для ограничения времени выполнения в ASP.NET Core отменяет токен отмены (CancellationToken), но не останавливает поток принудительно и не заставляет endpoint немедленно вернуть ответ. Чтобы таймаут действительно помогал, токен должен передаваться по всей цепочке вызовов: от endpoint через сервисы до EF Core или HttpClient. При этом вызываемый код тоже должен поддерживать отмену. В примере из статьи для endpoint установлен лимит в 3 секунды. Но если внутри него выполняется десятисекундная задержка, которая игнорирует токен отмены, обработка может продолжиться и завершиться ответом 200 OK. Проверить поведение можно в двух сценариях: когда операция корректно реагирует на отмену и когда игнорирует её. Тестировать нужно без подключённого отладчика — в описанном примере таймаут не срабатывает под отладчиком. Разбор настройки таймаутов и обработки отмены в ASP.NET Core 👉 @KodBlog
Rate Limiting в ASP.NET Core: одного middleware недостаточно Ограничение частоты запросов помогает защитить API от перебора паролей, злоупотребления запросами, резких скачков трафика и чрезмерного потребления ресурсов. Но полагаться только на middleware внутри приложения — ошибка. Защищать нужно всю цепочку обработки запросов: CDN и защита от DDoS → WAF → API Gateway → .NET API → внутренние сервисы Каждый уровень решает свои задачи: от фильтрации вредоносного трафика до ограничения нагрузки на приложение и зависимые сервисы. Надёжная защита API — это не одна настройка, а многоуровневый подход. 👉 @KodBlog
«Запрос использует индекс» — это ещё не значит, что с производительностью всё в порядке. Допустим, нужно получить последний комментарий к задаче. Индекс отсортирован сначала по ID задачи, затем по ID пользователя и только потом по дате. Он позволяет найти комментарии к нужной задаче, но внутри они сгруппированы по пользователям, а уже затем отсортированы по дате. Это не тот порядок, который нужен запросу, поэтому базе данных всё равно может потребоваться дополнительная сортировка. В запросе для дашборда такая работа может повторяться для каждой задачи. План выполнения запроса помогает проверить условия фильтрации, порядок сортировки и количество циклов выполнения. Для такого запроса лучше подойдёт индекс по ID задачи и дате. Но даже в этом случае нужно измерять производительность всего запроса. Дополнительные индексы занимают место и увеличивают нагрузку при записи данных. В примере с PostgreSQL показано, как порядок столбцов в индексе влияет на план выполнения. 👉 @KodBlog
Сны вайб-кодеров 🐺 👉 @KodBlog
Два запроса — одна квартира — двойное бронирование Оба запроса могут проверить доступность квартиры и увидеть свободные даты. Проблема возникает между проверкой и сохранением: за это время другой запрос успевает создать бронь. Один из способов защиты — оптимистическая конкуренция через общую строку квартиры. При создании бронирования каждый запрос также обновляет эту строку в одной транзакции. У неё есть токен версии, который меняется при обновлении. EF Core добавляет прочитанную версию в условие UPDATE. Первый запрос успешно сохраняет изменения. Второй использует уже устаревшую версию и получает DbUpdateConcurrencyException; его транзакция откатывается. После конфликта нельзя просто повторить запись. Нужно заново прочитать актуальные данные и проверить доступность дат. Версия только на новой строке бронирования здесь не поможет: запросы создают разные строки и не конфликтуют между собой. Разбор и пример на EF Core 👉 @KodBlog
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
Отдельная схема БД ещё не изолирует данные модуля Если все модули используют одну учётную запись PostgreSQL, она может иметь доступ ко всем таблицам. Названия папок и схем этих прав не меняют. Чтобы закрепить границы, каждому модулю можно выделить собственную роль с доступом только к его схеме и указать её в строке подключения. Тогда случайный запрос к приватной таблице другого модуля будет отклонён самой БД. При этом каждому модулю по-прежнему нужны свой DbContext и явный контракт доступа к общим данным. Для совместного чтения владеющий модуль может предоставить API или представление (VIEW) с намеренно выданными правами. Так границы модулей становятся проверяемым ограничением, а не просто договорённостью команды. Практическое руководство: роли PostgreSQL, права доступа и настройка EF Core 👉 @KodBlog
12 возможностей современного C#, которые стоит знать .NET-разработчику C# заметно изменился: лаконичный синтаксис, средства работы с null, улучшения производительности и инструменты для конкурентного выполнения задач помогают писать более понятный и надёжный код. Собрали 12 возможностей, которые пригодятся в повседневной разработке. 👉 @KodBlog
lock в C# не остановит второй экземпляр приложения Когда приложение работает в нескольких экземплярах, каждый может запустить одну и ту же задачу по расписанию. У каждого процесса свой lock в памяти. Для координации можно использовать advisory lock в PostgreSQL: оба экземпляра пытаются получить одну и ту же блокировку. Получивший запускает задачу, другой пропускает попытку. Но есть нюансы: • Сессионная блокировка удерживается соединением с БД. Если соединение потеряно, другой воркер может получить её, пока первый ещё выполняет работу. • Блокировка не хранит историю выполненных запусков — их нужно учитывать отдельно. • Повторное выполнение должно быть безопасным: блокировка сама по себе не гарантирует «ровно один раз». Разбор и пример на C# 👉 @KodBlog
Параллельное ожидание async-операций в .NET Не ожидайте независимые асинхронные операции по очереди. Запустите их сразу, а затем дождитесь завершения через Task.WhenAll() — общее время не будет складываться из времени каждой операции. 👉 @KodBlog
Если сохранять данные в БД и публиковать сообщение двумя отдельными шагами, сбой между ними может привести к потере сообщения. Outbox решает эту проблему: данные и сообщение сохраняются в одной транзакции, а фоновый обработчик позже отправляет сообщение брокеру. 👉 @KodBlog
Автоматическая регистрация зависимостей со Scrutor в ASP.NET Core Scrutor расширяет встроенный DI-контейнер: сканирует сборки, находит сервисы и регистрирует их по заданным правилам. Меньше ручных регистраций — особенно когда в проекте много однотипных сервисов. 👉 @KodBlog
Заказ сохранился, но так и не отправился Приложение записывает заказ в БД, затем публикует событие для запуска доставки. Если брокер недоступен, а приложение остановится до повторной попытки, событие может потеряться. Transactional Outbox помогает пережить такой сбой. Заказ и событие сохраняются в одной транзакции БД: либо фиксируются обе записи, либо ни одна. Фоновый обработчик читает таблицу outbox и отправляет события брокеру. Если отправка не удалась, запись остаётся для повторной попытки. Но есть нюанс: обработчик может отправить событие и упасть до того, как отметит его отправленным. После перезапуска сообщение уйдёт повторно. Поэтому получатель должен обрабатывать дубликаты безопасно. Повторное сообщение не должно приводить к повторной отправке заказа. Проверьте оба сценария: • Остановите брокер перед отправкой события. • Остановите обработчик после отправки, но до обновления записи в outbox. Разбор механизма и настройки в EF Core 👉 @KodBlog
Комментарии
Комментариев пока нет
Комментарии пишут вошедшие — так видно, кто автор.
Войти