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

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

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Изучайте алгоритмы — наглядно

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

https://algorithm-visualizer.org

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👏43
Вот хороший пример использования перехватчиков (interceptors) в EF: отслеживание того, когда ваши сущности были созданы или изменены.

Вы можете использовать ChangeTracker, чтобы проверить состояние сущности и установить соответствующие поля.

Если вы всегда используете этот DbContext в рамках HTTP-запроса, вы даже можете передавать UserId.
👍4👏2
Обработка «сырого» исключения базы данных при нарушении уникального ограничения приводит к появлению некрасивого DbUpdateException с вложенным provider-specific исключением, которое приходится по-разному парсить для SQL Server, PostgreSQL и SQLite.

Библиотека EntityFramework.Exceptions решает эту проблему.

https://github.com/Giorgi/EntityFramework.Exceptions

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
16 полезных сайтов, которые сделают тебя лучшим разработчиком:

1. roadmap.sh — дорожные карты для изучения dev-ролей
2. explainshell.com — объясняет каждый флаг в bash-командах
3. regex101.com — тестирование и отладка регулярных выражений с live-обратной связью
4. jsoncrack.com — превращает сырой JSON в визуальную диаграмму
5. bundlephobia.com — показывает размер npm-пакета до установки
6. transform.tools — мгновенно конвертирует между форматами для разработки
7. webhook.site — live URL для логирования webhook-запросов
8. devhints.io — шпаргалки по языкам и инструментам
9. httpie.io/app — браузерный HTTP-клиент для работы с API
10. caniuse.com — проверка поддержки CSS и JS в браузерах
11. squoosh.app — сжатие изображений прямо в браузере
12. carbon.now.sh — превращает код в аккуратные скриншоты
13. overapi.com — одностраничные шпаргалки по разным темам
14. shortcuts.design — горячие клавиши для популярных dev-инструментов
15. tinywow.com — бесплатный конвертер файлов
16. getfluently.app — прокачка разговорного английского с помощью AI

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥73👍3🍌1
CA1507: Используйте nameof вместо строкового литерала

У кого включено это правило анализа кода?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16👏1🍌1
Инжект настроек в .NET

У тебя есть 3 основных интерфейса на выбор. Но если выбрать не тот — приложение может просто игнорировать изменения конфигурации.

Вот простое объяснение:

1️⃣ IOptions
• Считывается один раз при старте приложения
• Кэшируется на весь жизненный цикл
• Подходит для статичных настроек, которые не меняются

2️⃣ IOptionsSnapshot
• Пересчитывается на каждый запрос
• Подхватывает изменения в appsettings.json без перезапуска
• Идеален для web API (Scoped lifetime)

3️⃣ IOptionsMonitor
• Обновляется в реальном времени
• Триггерит событие при изменении настроек
• Подходит для фоновых сервисов (Singleton lifetime)

Правило большого пальца (Rule of Thumb):
Используй IOptions для статической конфигурации.
Переходи на IOptionsSnapshot в веб-приложениях.
Используй IOptionsMonitor, когда нужны уведомления об изменениях в background-задачах.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
10🍌2
Мой любимый способ конфигурировать Serilog — через настройки приложения.

Можно настраивать уровни логирования, внешние sinks, enrichers и многое другое.

Это также значит, что конфигурацию Serilog можно менять без изменений в коде.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👏1
Большинство .NET-разработчиков реализуют кэширование сложным способом.

Они пишут шаблонный (boilerplate) код в каждом методе сервиса — проверяют кэш, делают запрос к базе, сохраняют результат, обрабатывают время жизни.

Есть способ лучше, который почти не требует изменений в коде.

Он называется Output Cache middleware в ASP.NET Core.

И работает он совершенно иначе, чем IMemoryCache или IDistributedCache.

Ключевое отличие:

-IMemoryCache и IDistributedCache кэшируют объекты внутри кода приложения
- Output Cache перехватывает HTTP-ответ на уровне middleware, сохраняет его целиком и отдает повторно

При наличии кэша не вызываются ни обработчик endpoint’а, ни запрос к базе, ни бизнес-логика.

Что делает Output Cache мощным:

- Добавление кэширования одним атрибутом — без boilerplate-кода в сервисах
- Встроенный cache lock предотвращает проблему «thundering herd»
- Именованные политики задают поведение кэша централизованно
- Инвалидация по тегам позволяет сбрасывать группы связанных записей одним вызовом
- Опции VaryBy позволяют кэшировать отдельные ответы по заголовкам, query string, route-параметрам или кастомной логике

Но вот где большинство разработчиков ошибается:
Кэшируют ответы авторизованных API без разделения по пользователям
→ Данные пользователя A могут быть отданы пользователю B
→ Это реальная уязвимость безопасности

Читать гайд

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
8😁2
Ищешь альтернативу Postman?
Apidog — это all-in-one инструмент для работы с API.

✓ Проектируй и управляй спецификациями API
✓ Мокай и тестируй endpoints в одном месте
✓ Генерируй документацию автоматически
✓ Тестируй интеграции с ИИ, такие как ChatGPT

Доступен в веб-версии и приложении с бесплатным тарифом:

http://midu.link/apidog

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
4😁4
Что такое breaking change для API?

Вот несколько примеров:

- Удаление или переименование API или параметров API
- Изменение поведения существующих API
- Изменение кодов ошибок API

Breaking change означает, что вам нужно версионировать API — иначе вы рискуете сломать существующих клиентов.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6😁1
Отличные ресурсы по системному дизайну
http://github.com/ashishps1/awesome-system-design-resources

Что внутри:

1. Базовые концепции — теорема CAP, консистентное хеширование, масштабируемость, доступность
2. Основы сетей — DNS, балансировка нагрузки, модель OSI, WebSockets
3. Глубокое погружение в базы данных — шардирование, репликация, SQL vs NoSQL
4. Разборы реальных систем — Twitter, Netflix, Uber, Google Drive
5. Включены диаграммы и примеры реализации кода

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
3🍌2
Большинство .NET-разработчиков используют AsNoTracking() время от времени — когда вспоминают.

Но очень немногие делают его поведением по умолчанию — и тем самым теряют реальную производительность.

Вот полная картина query tracking в EF Core, которую редко объясняют в одном месте.

Три метода. Одна цель: не трекать то, что вы не собираетесь менять.

AsNoTracking()

Самый быстрый вариант. Полностью обходит change tracker.

Идеален для любых read-only запросов — списки, результаты поиска, отчёты, фоновые задачи.

Есть один нюанс: если одна и та же сущность появляется через разные join’ы, EF Core создаст два разных C#-объекта в памяти вместо одного.

Это может незаметно ломать поведение.

AsNoTrackingWithIdentityResolution()

Даёт тот же плюс отсутствия трекинга, но решает проблему дубликатов объектов.

EF Core по-прежнему не использует change tracker, но поддерживает identity map, благодаря чему одна и та же сущность всегда соответствует одному и тому же C#-объекту.

Немного медленнее, чем чистый AsNoTracking, но правильный выбор для сложных запросов с Include.

UseQueryTrackingBehavior()

Перестаньте писать AsNoTracking в каждом запросе.

Задайте это глобально в DbContext при старте приложения.

Теперь все запросы по умолчанию — без трекинга.

А там, где нужно изменение данных, явно используйте AsTracking().

Используйте NoTracking, когда:

→ read-only API endpoint’ы
→ пагинация и списки
→ отчёты и экспорт данных
→ чтение данных в фоновых задачах
→ страницы с результатами поиска

Оставляйте tracking, когда:

→ загружаете сущность для последующего обновления
→ после запроса вызывается SaveChanges
→ мутируете сложные графы объектов
→ работаете с disconnected-сценариями сущностей

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥3😁1
DelegatingHandlers позволяют добавлять поведение до или после выполнения запросов через HttpClient.

Это как middleware, но для исходящих (outgoing) запросов.

Отличный кейс использования этой возможности?

Добавление заголовков аутентификации к запросу. 👇

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5👀2
Однажды я заплатил $40 за .NET-приложение с самописным ORM.

В нём были SQL-инъекции, сломанные транзакции и ноль тестов.

Вот 6 ORM-репозиториев, которые действительно стоят внимания:

1. Entity Framework Core - https://github.com/dotnet/efcore
2. Dapper - https://github.com/DapperLib/Dapper
3. NHibernate - https://github.com/nhibernate/nhibernate-core
4. linq2db - https://github.com/linq2db/linq2db
5. Marten - https://github.com/JasperFx/marten
6. SqlKata - https://github.com/sqlkata/querybuilder

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
4😁2👍1
Этот динамический парсинг JSON уже не раз меня подводил — я обычно кастую к string через as string, где это возможно.

В JSON.NET (JObject / JValue) значения ведут себя как dynamic при цепочках обращений, но при этом не кастуются, потому что по сути это Expando-подобные объекты.

Не первый раз на это натыкаюсь, и, скорее всего, не последний 😂

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤩1🍾1
Модули в модульном монолите могут взаимодействовать только через свой публичный API.

Но как это обеспечить на уровне архитектуры?

С помощью тестирования архитектуры.

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

[Fact]
public void TicketingModule_ShouldNotHaveDependencyOn_AnyOtherModule()
{
string[] otherModules = [
UsersNamespace,
EventsNamespace,
AttendanceNamespace
];

string[] integrationEventsModules = [
UsersIntegrationEventsNamespace,
EventsIntegrationEventsNamespace,
AttendanceIntegrationEventsNamespace
];

List<Assembly> ticketingAssemblies =
[
typeof(Order).Assembly,
Modules.Ticketing.Application.AssemblyReference.Assembly,
Modules.Ticketing.Presentation.AssemblyReference.Assembly,
typeof(TicketingModule).Assembly
];

Types.InAssemblies(ticketingAssemblies)
.That()
.DoNotHaveDependencyOnAny(integrationEventsModules)
.Should()
.NotHaveDependencyOnAny(otherModules)
.GetResult()
.ShouldBeSuccessful();
}


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42🍾1
Кто-то собрал все задачи с LeetCode, сгруппированные по компаниям, и выложил это в публичный репозиторий на GitHub. Более 300 компаний: Google, Meta, Amazon, Jane Street, Citadel, Stripe, Snowflake — практически каждый крупный работодатель в техе, у каждого своя папка.

Внутри папок всё отсортировано по тому, насколько недавно задача встречалась — за последние 30 дней, 60 дней, 90 дней и за всё время.

Это означает, что если у тебя интервью в Google в пятницу, ты можешь открыть папку Google и увидеть, какие задачи они задавали в этом месяце.

Не самая приятная правда, которая здесь вскрывается: компании месяцами переиспользуют одни и те же задачи. Интервью — это не непредсказуемое испытание, а набор паттернов. А паттерны можно изучать.

Большинство кандидатов решают 500 случайных задач на LeetCode и надеются на лучшее. Те, кто знают про этот репозиторий, тратят то же время на 30 задач, которые их целевая компания задавала за последние 30 дней.

Те же усилия. Совершенно другие шансы.

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

Лично я этим не пользовался, делюсь на случай, если кому-то пригодится.

P.S. Мы всё ещё решаем LeetCode в 2026?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3🤔1
Пользовательские SQL-запросы в миграциях EF? Это возможно.

Пользовательские SQL-команды полезны, когда мы не можем выразить что-то через Fluent API EF.

Я использовал их для переноса данных из одного столбца в другой или для создания сложных индексов.

- Создайте пустую миграцию
- Напишите свои SQL-запросы

public partial class Update_Products : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("<YOUR CUSTOM SQL HERE>");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
// You are also responsible for reverting any changes.
}
}


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👏3👍2
Младший разработчик использует EF Core напрямую в контроллере.

Средний разработчик использует BaseRepository, IUnitOfWork, IOrderRepository, IOrderDataAccess, IOrderQueryBuilder.

Старший разработчик использует EF Core без репозитория.

Когда ваше приложение маленькое, использование паттерна Репозиторий кажется простым.

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

По мере роста вашего домена вы сталкиваетесь со следующими проблемами:

- Вы создаете репозиторий для каждой новой сущности
- Куда относятся методы, работающие с несколькими сущностями?
- Вы создаете репозитории с 10-20 методами

Я часто слышу следующие распространенные оправдания для использования репозиториев:

𝟭. "Мы можем позже сменить базу данных."

В 99% случаев вам не нужно будет менять базу данных.

- Переход от одной SQL базы данных к другой? EF Core справится с этим.
- Использование хранимых процедур, триггеров? Тогда их нужно переписать на уровне базы данных.
- Переход от реляционной базы данных к документной? Вам нужно будет изменить модель данных, запросы и шаблоны доступа. Вы не сможете просто заменить реализации репозиториев.

𝟮. "Это облегчает тестирование."

Некоторые утверждают, что мокирование репозитория проще, чем мокирование DbContext.

Но это скрывает большую проблему: вы тестируете абстракцию абстракции.

Мокирование репозиториев часто приводит к хрупким тестам, которые не отражают реальное поведение запросов.

Вместо этого лучше использовать реальный EF Core с базой данных в памяти или, что еще лучше, писать интеграционные тесты.

𝟯. "Это обеспечивает разделение ответственностей."

Репозитории часто используются для того, чтобы держать бизнес-слой отдельно от EF Core. Но на практике это разделение создает больше путаницы, чем ясности.

По мере того как ваши фичи растут, вам приходится:

- Внедрять несколько репозиториев в ваши сервисы
- Или переносить логику, работающую с несколькими сущностями, в жирный репозиторий

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

DbContext в EF Core уже реализует паттерны Репозиторий и Unit of Work, как указано в официальном описании кода DbContext.

Я использую EF Core напрямую в кейсах использования и сервисах моего приложения. Это прагматичный подход, который приносит мне больше преимуществ, чем недостатков.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11💯6👎21👏1
𝟭𝟱 инструментов и библиотек .NET, которые использует сообщество

Я задал в r/dotnet один вопрос: какие библиотеки .NET вы реально используете, о которых никто не говорит?

Тред собрал сотни ответов. Я отфильтровал те, у которых 10+ апвоутов.

CSharpier набрал 62 голоса. Refit — на втором месте. Дальше — набор инструментов с 30–31 голосами, о большинстве из которых разработчики либо не знают, либо почти не упоминают в туториалах.

Несколько моментов, которые бросились в глаза:

Сообщество стало скептически относиться к зависимостям. FluentAssertions, IdentityServer и MediatR — к ним уже нет прежнего доверия. Самый залайканный комментарий (не про библиотеку) был: «Batteries included, stay away from dependencies» (используй встроенные возможности и избегай лишних зависимостей). Этот контекст важен при чтении списка.

LINQPad — это не NuGet-пакет, но он постоянно всплывал в обсуждении. Команды строят на нём целые вспомогательные воркфлоу.

Vogen меня удивил. Type-safe value objects, генерируемые на этапе компиляции без runtime-оверхеда. Я видел баги в продакшене из-за путаницы с orderId/customerId — это как раз решает такие проблемы.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
😁1
Как версионировать Minimal API?

Нужно определить ApiVersionSet и применить его к эндпоинтам.

Более удобный подход — создать route group, назначить ему версию API, а затем использовать этот route group для маппинга отдельных эндпоинтов.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2👀1