Записи действительно являются неизменяемыми.
Если вы знаете, как их определять.
Если запись объявлена традиционным способом, нет ограничений на использование обычного сеттера, что позволяет изменять объект после инициализации.
Однако, если в записи используется init только для части свойств, то такая запись не является полностью неизменяемой.
Так как же сделать их неизменяемыми?
Используйте позиционные записи.
Такой тип записей компилятор генерирует со свойствами только для инициализации (init-only).
Может показаться, что первый и второй вариант определения идентичны.
Но позвольте развеять это заблуждение.
Первая форма компилируется во вторую, и во втором случае вы можете заменить🐸
👉 @KodBlog
Если вы знаете, как их определять.
Если запись объявлена традиционным способом, нет ограничений на использование обычного сеттера, что позволяет изменять объект после инициализации.
Однако, если в записи используется init только для части свойств, то такая запись не является полностью неизменяемой.
Так как же сделать их неизменяемыми?
Используйте позиционные записи.
Такой тип записей компилятор генерирует со свойствами только для инициализации (init-only).
Может показаться, что первый и второй вариант определения идентичны.
Но позвольте развеять это заблуждение.
Первая форма компилируется во вторую, и во втором случае вы можете заменить
init
на set
и тем самым нарушить основную характеристику записей. Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🔥1🥴1
MongoDB теперь нативно доступен на Azure.
Больше никаких "костылей" между сервисами.
Теперь можно:
> Запускать MongoDB Atlas напрямую из Azure Portal
> Интегрироваться с Azure AI, Databricks, OpenAI — в одном потоке
> Получать единый биллинг по всему стеку
Это будущее cloud-native разработки?
Или тесная интеграция с облаком — палка о двух концах для свободы разработчиков?
Полная разбивка: https://fnf.dev/4n1fsLd✌️
👉 @KodBlog
Больше никаких "костылей" между сервисами.
Теперь можно:
> Запускать MongoDB Atlas напрямую из Azure Portal
> Интегрироваться с Azure AI, Databricks, OpenAI — в одном потоке
> Получать единый биллинг по всему стеку
Это будущее cloud-native разработки?
Или тесная интеграция с облаком — палка о двух концах для свободы разработчиков?
Полная разбивка: https://fnf.dev/4n1fsLd
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3
Сократил время выполнения SQL-запроса с 70 мс до 1 мс.
Без изменений в коде. Без кэширования. Просто добавил filtered index (фильтрованный индекс).
Фильтрованные индексы — одна из самых недооценённых возможностей SQL.
Они позволяют индексировать только подмножество строк, соответствующих определённому условию — идеально подходят для флагов вроде
Но есть нюанс: если условие выполняется для большинства строк, индекс не даст прироста производительности.
Эта оптимизация дала огромный прирост в одном из проектов.
В статье подробно разбирается реализацию и показывается, как это использовать: читать
👉 @KodBlog
Без изменений в коде. Без кэширования. Просто добавил filtered index (фильтрованный индекс).
Фильтрованные индексы — одна из самых недооценённых возможностей SQL.
Они позволяют индексировать только подмножество строк, соответствующих определённому условию — идеально подходят для флагов вроде
ProcessedAt IS NULL
.Но есть нюанс: если условие выполняется для большинства строк, индекс не даст прироста производительности.
Эта оптимизация дала огромный прирост в одном из проектов.
В статье подробно разбирается реализацию и показывается, как это использовать: читать
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14
В EF Core 9 улучшена функция
Небольшое, но полезное улучшение.
Эта возможность появилась в EF Core 8 — для производительного обновления данных в базе без загрузки в память.
Однако изначально она поддерживала только примитивные типы.
Если нужно было обновить комплексный тип, приходилось вручную перечислять все его свойства… до выхода EF Core 9.
Теперь комплексные типы полностью поддерживаются — больше не нужно делать это вручную🙂
👉 @KodBlog
ExecuteUpdate
Небольшое, но полезное улучшение.
Эта возможность появилась в EF Core 8 — для производительного обновления данных в базе без загрузки в память.
Однако изначально она поддерживала только примитивные типы.
Если нужно было обновить комплексный тип, приходилось вручную перечислять все его свойства… до выхода EF Core 9.
Теперь комплексные типы полностью поддерживаются — больше не нужно делать это вручную
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤5🔥1
Rider 2025.2 EAP 4 уже тут
Этот билд приносит поддержку SQL-проектов базы данных через встроенный плагин — без доп. настройки:
> Шаблоны SQL-проектов в стиле SDK
> Сравнение схем и публикация проекта
> Импорт из БД, добавление ссылок и другое
Подробнее > jetbrains.com/rider/nextversion🐸
👉 @KodBlog
Этот билд приносит поддержку SQL-проектов базы данных через встроенный плагин — без доп. настройки:
> Шаблоны SQL-проектов в стиле SDK
> Сравнение схем и публикация проекта
> Импорт из БД, добавление ссылок и другое
Подробнее > jetbrains.com/rider/nextversion
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥5👏2🤔2
Улучшения производительности
👉 @KodBlog
FrozenDictionary
с целочисленными (int
) ключами в .NET 10FrozenDictionary
представляют собой коллекции, оптимизированные для чтения (Dictionary
и Set
), создание которых занимает больше времени, но чтение из них происходит быстрее по сравнению с неизменяемыми (immutable
) коллекциями.Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🔥1
В чём проблема с синглтоном (Singleton) в многопоточности?
Как реализовать потокобезопасный синглтон?
Две нити (потока) могут одновременно проверить, является ли экземпляр null, и обе получат true.
В результате каждая из них создаст собственный экземпляр, что нарушает основное правило паттерна Singleton — наличие только одного экземпляра.
Кроме того, экземпляр может быть уже создан до этой проверки, но другие потоки могут не увидеть его сразу, если не принять меры для обеспечения корректной видимости.
Как сделать реализацию потокобезопасной?
Один из распространённых способов — использование блокировки (locking), например, с применением double-check locking (двойной проверки).
Однако это сложный способ, и при неправильной реализации может привести к ошибкам.
Какое решение лучше?
На мой взгляд, универсального «лучшего» решения нет — всё зависит от конкретной ситуации. Мне нравится и я рекомендую использовать Lazy.
Вот как можно реализовать паттерн Singleton с использованием Lazy:
>
>
>
Такой подход рекомендуется в современной разработке на C#, поскольку он использует встроенные возможности .NET Framework для безопасной инициализации в многопоточной среде.🙂
👉 @KodBlog
Как реализовать потокобезопасный синглтон?
Две нити (потока) могут одновременно проверить, является ли экземпляр null, и обе получат true.
В результате каждая из них создаст собственный экземпляр, что нарушает основное правило паттерна Singleton — наличие только одного экземпляра.
Кроме того, экземпляр может быть уже создан до этой проверки, но другие потоки могут не увидеть его сразу, если не принять меры для обеспечения корректной видимости.
Как сделать реализацию потокобезопасной?
Один из распространённых способов — использование блокировки (locking), например, с применением double-check locking (двойной проверки).
Однако это сложный способ, и при неправильной реализации может привести к ошибкам.
Какое решение лучше?
На мой взгляд, универсального «лучшего» решения нет — всё зависит от конкретной ситуации. Мне нравится и я рекомендую использовать Lazy.
Вот как можно реализовать паттерн Singleton с использованием Lazy:
>
Lazy Initialization:
Класс Lazy автоматически управляет отложенной инициализацией экземпляра Singleton. Экземпляр создаётся только при первом обращении.>
Потокобезопасность:
Lazy обеспечивает создание экземпляра в потокобезопасном режиме, поэтому нет необходимости использовать блокировки или double-check locking вручную.>
Простота и сопровождаемость:
Код становится проще и легче поддерживать, так как вся логика синхронизации инкапсулирована внутри Lazy.Такой подход рекомендуется в современной разработке на C#, поскольку он использует встроенные возможности .NET Framework для безопасной инициализации в многопоточной среде.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤5
Внедрение настроек в .NET? Существует три основных интерфейса:
>
>
>
Используйте
Подробнее о том, как работает паттерн Options и когда какой интерфейс использовать: read
👉 @KodBlog
>
IOptions:
кэшируется на всё время жизни приложения>
IOptionsSnapshot:
переоценивается при каждом запросе (scoped)>
IOptionsMonitor:
позволяет получать текущее значение и реагировать на измененияИспользуйте
IOptions
для статической конфигурации, IOptionsSnapshot
— в веб-приложениях, где конфигурация может меняться между запросами, а IOptionsMonitor
— когда нужно отслеживать изменения настроек.Подробнее о том, как работает паттерн Options и когда какой интерфейс использовать: read
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥2
EF Core:
👉 @KodBlog
DbContextOptionsBuilder
используется для настройки DbContext
, как показано в примере для консольного проекта. Также он может применяться вместе с внедрением зависимостей (dependency injection)Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Ставить точку или не ставить точку в сообщениях об исключениях? 👀
Байкшеддинг (bikeshedding) — большая проблема в нашей сфере.
Что такое "Bikeshedding"?
"Bikeshedding" — это феномен, также известный как закон тривиальности Паркинсона, при котором в организации несоразмерно много внимания уделяется незначительным вопросам. Это часто происходит на встречах: сложные темы быстро проходят без обсуждения (из-за нехватки знаний), а простые и понятные, вроде оформления сообщений об ошибках вызывают долгие споры.
Термин введён в книге Паркинсона "Law of Triviality". В ней описывается вымышленный комитет, обсуждающий проект ядерного реактора. Технические детали реактора одобряются без вопросов, никто не понимает их глубоко. А вот над проектом велосипедного сарая (bike shed) ведутся долгие дебаты: это всем понятно, каждый хочет высказаться.
Вот типичные примеры bikeshedding в разработке ПО — темы, на которые часто тратится непропорционально много времени, хотя они имеют минимальное влияние на результат:
Стиль кода и форматирование
> Tabs vs. spaces (табуляция или пробелы)
> Максимальная длина строки
> Расположение фигурных скобок {}
> Стиль комментариев и выравнивание docstring'ов
> Формат именования переменных (
Выборы в 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
Байкшеддинг (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 в простом фронте
Технический педантизм
> Оверинжиниринг мелкой фичи "на будущее"
> Дебаты: функциональный подход или ООП в хелпере
> Внедрение шаблона проектирования там, где он не нужен
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤7😁4
10 «секретных» ключевых слов в C#, которые используют синьоры, но не знают мидлы и джуны
Что это за ключевые слова?👇
> extension
Новое ключевое слово в C# 14
Позволяет добавлять методы к уже существующим классам без изменения их исходного кода. Идеально подходит для чистого расширения поведения с новыми возможностями.
> await using
Вызывает
> when (catch)
Фильтрует исключения в блоках catch на основе условий.
> partial
Разделяет определение класса на несколько файлов. Удобно для автогенерируемого кода или логической организации больших классов.
> readonly struct
Определяет неизменяемый тип значения (value type) с поведением сравнения по значению по умолчанию.
> in
Передаёт параметры по ссылке как только для чтения. Избегает лишнего копирования больших структур, повышая производительность без потери безопасности.
> extern
Указывает, что метод реализован вне текущего кода, как правило, в нативной библиотеке (DLL). Позволяет подключать неуправляемые библиотеки.
> volatile
Гарантирует, что значение поля всегда читается из основной памяти — важно в многопоточном коде. Помогает избегать тонких ошибок синхронизации.
> unsafe
Включает использование указателей и арифметику с ними, а также прямую работу с памятью.
> stackalloc
Выделяет память напрямую в стеке, а не в куче. Подходит для краткоживущих, высокопроизводительных сценариев.
👉 @KodBlog
Что это за ключевые слова?
> extension
Новое ключевое слово в C# 14
Позволяет добавлять методы к уже существующим классам без изменения их исходного кода. Идеально подходит для чистого расширения поведения с новыми возможностями.
> await using
Вызывает
IAsyncDisposable
для асинхронного освобождения ресурсов.> when (catch)
Фильтрует исключения в блоках catch на основе условий.
> partial
Разделяет определение класса на несколько файлов. Удобно для автогенерируемого кода или логической организации больших классов.
> readonly struct
Определяет неизменяемый тип значения (value type) с поведением сравнения по значению по умолчанию.
> in
Передаёт параметры по ссылке как только для чтения. Избегает лишнего копирования больших структур, повышая производительность без потери безопасности.
> extern
Указывает, что метод реализован вне текущего кода, как правило, в нативной библиотеке (DLL). Позволяет подключать неуправляемые библиотеки.
> volatile
Гарантирует, что значение поля всегда читается из основной памяти — важно в многопоточном коде. Помогает избегать тонких ошибок синхронизации.
> unsafe
Включает использование указателей и арифметику с ними, а также прямую работу с памятью.
> stackalloc
Выделяет память напрямую в стеке, а не в куче. Подходит для краткоживущих, высокопроизводительных сценариев.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤20🤣3👍2🔥1
Хочешь отслеживать изменения в базе данных в реальном времени?
Я реализовал Change Data Capture (CDC) в .NET с использованием Debezium, PostgreSQL и RabbitMQ.
Поток обработки:
> PostgreSQL настроен на генерацию событий об изменениях
> Debezium перехватывает эти изменения
> События публикуются в RabbitMQ
> MassTransit в .NET потребляет и обрабатывает их
Это лишь один из способов реализации архитектуры, основанной на событиях (Event-Driven Architecture).
Если ты проектируешь распределённые системы в .NET — вот полный гайд по созданию event-driven-систем с RabbitMQ♟
👉 @KodBlog
Я реализовал Change Data Capture (CDC) в .NET с использованием Debezium, PostgreSQL и RabbitMQ.
Поток обработки:
> PostgreSQL настроен на генерацию событий об изменениях
> Debezium перехватывает эти изменения
> События публикуются в RabbitMQ
> MassTransit в .NET потребляет и обрабатывает их
Это лишь один из способов реализации архитектуры, основанной на событиях (Event-Driven Architecture).
Если ты проектируешь распределённые системы в .NET — вот полный гайд по созданию event-driven-систем с RabbitMQ
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11🔥3
Видишь баг?
9 из 10 разработчиков пропускают его. Проверь себя
Проблема:
>
> Если
Решение:
✅ Явно оборачивай все такие команды в транзакцию вручную
Мелочь, а последствия могут быть серьёзные😨
👉 @KodBlog
9 из 10 разработчиков пропускают его. Проверь себя
Проблема:
>
ExecuteUpdateAsync
и ExecuteDeleteAsync
обходят Change Tracker в EF Core> Если
SaveChangesAsync()
потом упадёт — обновления в базе не откатятся автоматическиРешение:
Мелочь, а последствия могут быть серьёзные
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤3🎉1
5 недооценённых LINQ-методов, которые мгновенно улучшают твой код:
1.
2.
3.
4.
5.
Бонус, который почти попал в топ:
>
>
>
>
>
LINQ — кладезь полезных методов, если знаешь, где копать💪
👉 @KodBlog
1.
Zip
— объединяет две последовательности в пары2.
Chunk
— разбивает коллекцию на чанки фиксированного размера3.
OfType<T>()
— фильтрует элементы по типу4.
DistinctBy
— возвращает уникальные элементы по заданному ключу5.
SelectMany
— разворачивает вложенные коллекции в плоский списокБонус, который почти попал в топ:
>
SequenceEqual
— сравнивает две коллекции на равенство>
Aggregate
— накапливает значение с помощью функции (reduce)>
GroupJoin
— объединяет по группам (аналог LEFT OUTER JOIN)>
ToLookup
— создает коллекцию, похожую на Dictionary, но с множеством значений>
Intersect
— возвращает пересечение двух коллекцийLINQ — кладезь полезных методов, если знаешь, где копать
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤12🔥10
Вы правильно внедряете зависимости в контроллеры?
Многие разработчики об этом не знают👇
В контроллер можно внедрить зависимости двумя способами:
↳ через конструктор
↳ через метод (endpoint)
Вы когда-нибудь работали с перегруженными контроллерами, в конструкторы которых передаётся слишком много зависимостей?
А вызываемый endpoint использует только часть из них.
❌ Это приводит к перерасходу памяти, так как все зависимости из конструктора выделяются в куче при каждом вызове контроллера — даже если они не используются.
✅ Так зачем не внедрять нужные объекты прямо в метод endpoint’а?
Для этого больше не требуется аннотация [FromServices] — как и в Minimal API.
Внедряя зависимости только там, где они реально нужны, вы повышаете читаемость, удобство поддержки и производительность контроллеров.
👉 @KodBlog
Многие разработчики об этом не знают
В контроллер можно внедрить зависимости двумя способами:
↳ через конструктор
↳ через метод (endpoint)
Вы когда-нибудь работали с перегруженными контроллерами, в конструкторы которых передаётся слишком много зависимостей?
А вызываемый endpoint использует только часть из них.
Для этого больше не требуется аннотация [FromServices] — как и в Minimal API.
Внедряя зависимости только там, где они реально нужны, вы повышаете читаемость, удобство поддержки и производительность контроллеров.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🤔3😁1
Визуализатор планов SQL-запросов для Entity Framework
Расширение EFCore.Visualizer для Visual Studio может стать настоящим прорывом.
Оно позволяет разработчикам просматривать план выполнения SQL-запросов напрямую внутри Visual Studio.
А ты уже пробовал?☺️
👉 @KodBlog
Расширение EFCore.Visualizer для Visual Studio может стать настоящим прорывом.
Оно позволяет разработчикам просматривать план выполнения SQL-запросов напрямую внутри Visual Studio.
А ты уже пробовал?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍4❤3
Секреты оптимизации SQL-запросов
Вот 20 проверенных техник, которые я регулярно использую для оптимизации SQL-запросов:😊
👉 @KodBlog
Вот 20 проверенных техник, которые я регулярно использую для оптимизации SQL-запросов:
• Грамотно используйте индексы:
Индексируйте критически важные столбцы, используемые в WHERE, JOIN, ORDER BY и GROUP BY.
• Избегайте SELECT *:
Выбирайте только необходимые столбцы, чтобы сократить объём передаваемых данных и время обработки.
• Реализуйте пагинацию корректно:
Используйте OFFSET и FETCH NEXT или пагинацию методом поиска (seek method) для эффективного постраничного вывода.
• Ограничивайте количество строк как можно раньше:
Применяйте фильтрацию на ранних этапах, чтобы максимально сократить размер выборки.
• Избегайте функций в WHERE:
Функции над столбцами блокируют использование индексов — переписывайте условия, используя «сырые» столбцы.
• Упрощайте JOIN:
Минимизируйте количество соединений и избегайте избыточных JOIN-ов.
• Выбирайте правильные типы JOIN:
Используйте INNER JOIN, LEFT JOIN или EXISTS там, где это уместно, чтобы избежать лишней обработки данных.
• Используйте корректные типы данных:
Сопоставляйте типы данных в JOIN и WHERE, чтобы обеспечить эффективное использование индексов.
• Запрашивайте только изменённые данные:
Реализуйте инкрементальную обработку, а не полный повторный запрос таблиц.
• Группируйте операции:
Пакетная вставка, обновление или удаление снижают накладные расходы на транзакции.
• Исключайте избыточные подзапросы:
Используйте JOIN или CTE вместо повторяющихся подзапросов.
• Используйте EXISTS вместо IN:
EXISTS часто работает быстрее, чем IN, особенно на больших объёмах данных.
• Нормализуйте с умом:
Балансируйте между нормализацией и денормализацией в производительно критичных запросах.
• Применяйте материализованные представления:
Предварительно рассчитывайте сложные агрегации и запросы для ускорения чтения.
• Анализируйте планы выполнения:
Регулярно проверяйте execution plan, чтобы находить и устранять ресурсоёмкие операции.
• Избегайте подстановок с начальным %:
LIKE '%abc' не использует индексы эффективно.
• Делайте транзакции короткими:
Сокращайте время выполнения транзакций, чтобы уменьшить блокировки и конфликты.
• Регулярно обновляйте статистику:
Актуальные статистики обеспечивают точное планирование запросов СУБД.
• Используйте подсказки (query hints) с осторожностью:
Применяйте только после тестирования и при необходимости конкретной оптимизации.
• Постоянно отслеживайте и настраивайте:
Регулярно анализируйте производительность запросов и проактивно оптимизируйте медленные запросы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤4
Нужно генерировать PDF-отчёты в C#?
Вот простой и гибкий подход, который я использую, например, для счетов:
> Определите шаблон с помощью Razor View
> Преобразуйте Razor в HTML
> Сконвертируйте HTML в PDF (например, с помощью IronPdf, DinkToPdf или wkhtmltopdf)
Вы получаете полный контроль над стилями, и это легко интегрируется в существующие .NET-приложения.
Рабочую версию можно собрать менее чем за час.
▶️ Полный пример здесь: here
👉 @KodBlog
Вот простой и гибкий подход, который я использую, например, для счетов:
> Определите шаблон с помощью Razor View
> Преобразуйте Razor в HTML
> Сконвертируйте HTML в PDF (например, с помощью IronPdf, DinkToPdf или wkhtmltopdf)
Вы получаете полный контроль над стилями, и это легко интегрируется в существующие .NET-приложения.
Рабочую версию можно собрать менее чем за час.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍2🔥2
Создание и управление PDF-документами — это распространённая и критически важная задача для многих приложений, разработанных на .NET. Часто требуется генерировать счета, отчёты, договоры или преобразовывать содержимое из веб-страниц и других форматов.
Чтобы обеспечивать профессиональное качество документов без задержек, необходима надёжная PDF-библиотека.
В этом материале мы рассмотрим следующие темы:
🔸 Создание PDF-документов с нуля.
🔸 Конвертация между PDF и другими популярными форматами.
🔸 Практические сценарии генерации PDF-документов в
🔸 Сравнение популярных PDF-библиотек по критериям: производительность, удобство использования, опыт разработчика, документация, поддержка и лицензирование.
Мы рассмотрим следующие библиотеки для .NET:
> QuestPDF
> IronPDF
> Aspose.PDF
В результате вы сможете определить, какая библиотека наилучшим образом соответствует требованиям вашего проекта, что позволит сэкономить время и обеспечить профессиональную обработку PDF в вашем приложении❤️
👉 @KodBlog
Чтобы обеспечивать профессиональное качество документов без задержек, необходима надёжная PDF-библиотека.
В этом материале мы рассмотрим следующие темы:
ASP.NET Core
.Мы рассмотрим следующие библиотеки для .NET:
> QuestPDF
> IronPDF
> Aspose.PDF
В результате вы сможете определить, какая библиотека наилучшим образом соответствует требованиям вашего проекта, что позволит сэкономить время и обеспечить профессиональную обработку PDF в вашем приложении
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍3
Два шаблона, которые должен учитывать каждый распределённый система:
> Оркестрация — централизованное управление; один сервис координирует поток выполнения.
> Хореография — децентрализованное управление; сервисы реагируют на события самостоятельно.
Компромиссы:
> Оркестрация даёт больше контроля, но приводит к более жёсткой связности (tight coupling).
> Хореография лучше масштабируется, но усложняет координацию.
Выбор между ними зависит от требуемого уровня контроля, связности и автономности сервисов.
Здесь — более подробное сравнение обоих подходов.🙂
👉 @KodBlog
> Оркестрация — централизованное управление; один сервис координирует поток выполнения.
> Хореография — децентрализованное управление; сервисы реагируют на события самостоятельно.
Компромиссы:
> Оркестрация даёт больше контроля, но приводит к более жёсткой связности (tight coupling).
> Хореография лучше масштабируется, но усложняет координацию.
Выбор между ними зависит от требуемого уровня контроля, связности и автономности сервисов.
Здесь — более подробное сравнение обоих подходов.
Please open Telegram to view this post
VIEW IN TELEGRAM
😐2