C# (C Sharp) programming
По всем вопросам- @notxxx1 Реестр РКН: https://clck.ru/3Fk3kb #VRHSZ
Больше📈 Аналитический обзор Telegram-канала C# (C Sharp) programming
Канал C# (C Sharp) programming (@csharp_ci) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 18 042 подписчиков, занимая 7 244 место в категории Технологии и приложения и 36 510 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 18 042 подписчиков.
Согласно последним данным от 27 октября, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило -40, а за последние 24 часа — -15, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 15.81%. В первые 24 часа после публикации контент обычно набирает 8.23% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 2 853 просмотров. В течение первых суток публикация набирает 1 486 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 0.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как .net, api, логика, архитектура, string.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“По всем вопросам- @notxxx1
Реестр РКН: https://clck.ru/3Fk3kb
#VRHSZ”
Благодаря высокой частоте обновлений (последние данные получены 28 октября, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
SaveChanges, можно выполнить обновление одним SQL-запросом.
Это значительно быстрее и снижает нагрузку на приложение, особенно при работе с большими таблицами.
Однако есть важное условие: нужно заранее знать, какое поле вы обновляете и какое значение ему присваиваете, поскольку операция формируется как прямой SQL-update.
Такой подход отлично подходит для массовых операций и оптимизации производительности в EF Core.init
- структурное сравнение (Value Equality)
- короткий и чистый синтаксис
- deconstruction
- pattern matching
Пример:
public class Booking
{
public Address Address { get; init; }
public DateRange Period { get; init; }
}
public record Address(
string Street,
string City,
string State,
string Country,
string ZipCode);
Теперь два Address считаются равными, если совпадают их поля - без переопределения Equals и GetHashCode.
Раньше для value object приходилось писать:
• конструкторы
• Equals
• GetHashCode
• оператор ==
Теперь - одна строка.
Records делают value objects:
• безопаснее
• проще
• ближе к функциональному стилю
Если используете DDD в .NET - records должны быть стандартом для value objects.
services.AddHttpClient<GitHubService>(static httpClient =>
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
})
.AddStandardResilienceHandler();
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
public ExceptionHandlingMiddleware(
RequestDelegate next,
ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception exception)
{
_logger.LogError(
exception, "Exception occurred: {Message}", exception.Message);
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "Server Error"
};
context.Response.StatusCode =
StatusCodes.Status500InternalServerError;
await context.Response.WriteAsJsonAsync(problemDetails);
}
}
}
await _domainEventsDispatcher.DispatchAsync(
[new UserRegisteredDomainEvent(user.Id, user.Email)]
);
Дальше система реагирует сама:
- отправка приветственного письма
- трекинг в аналитике
- интеграции
- любые новые сценарии
И всё это без изменения UserService.
Преимущества:
- никаких жёстких зависимостей
- сервисы меньше и чище
- легче тестировать
- проще масштабировать
- новые фичи добавляются без переписывания существующего кода
Публикуешь один раз - система расширяется сама.ChangeTracker на сущности с интерфейсом ISoftDeletable
- Если состояние сущности — Deleted
- Меняет его на Modified
- Устанавливает:
- IsDeleted = true
- DeletedOnUtc = DateTime.UtcNow
В итоге:
Вы вызываете обычный:
context.Remove(entity);
А в базе:
- запись не удаляется
- просто помечается как удалённая
Плюсы подхода:
- никакой логики soft delete в сервисах и репозиториях
- единая точка обработки
- чистый доменный код
- безопасное удаление по всему приложению
Важно:
Если у вас есть связанные сущности (navigation properties),
перехватчик нужно дополнительно расширить — каскадное soft-удаление EF Core не делает автоматически.
Soft delete через interceptor — это один из самых чистых production-подходов для EF Core.
#dotnet #EFCore #Backend #Architecture #CSharpThread.Sleep —
готовьтесь к:
- медленным тестам
- flaky-падениям
- ненависти от CI/CD
Решение — Retry Assertion (Polling)
Как работает паттерн:
1. Выполняем команду (Module A)
2. Периодически опрашиваем состояние (Module B)
3. Ждём, пока результат появится
4. Делаем assert
Схема:
- Execute Command (Module A)
- Poll Query (Module B) until result != null
- Assert
Почему это лучше:
- Нет случайных падений
- Тесты работают быстрее
- Полностью детерминированное поведение
- Отлично подходит для async, событий и modular monolith
Главная идея:
Не жди фиксированное время — жди состояние.
Такой подход превращает нестабильные интеграционные тесты в надёжные и быстрые.IServiceProvider.
Внутри неё можно:
- получить любой сервис
- определить текущего пользователя или tenant
- выбрать нужную базу данных
- и только после этого установить строку подключения
Пример
builder.Services.AddDbContext<OrdersDbContext>((sp, o) =>
{
var tenantProvider = sp.GetRequiredService<TenantProvider>();
var connectionString = tenantProvider.GetConnectionString();
o.UseSqlServer(connectionString);
});
Dynamic DbContext configuration - ключевой паттерн для масштабируемых multi-tenant систем.
Если приложение растёт и базы начинают разделяться по клиентам или регионам, этот подход становится стандартом архитектуры.Thread.Sleep — готовьтесь к:
- медленным тестам
- flaky-поведению
- падениям в CI/CD
Решение — не ждать. Опрос (Polling).
Я использую паттерн Retry Assertion для тестирования асинхронного взаимодействия между модулями:
Как это работает:
1. Выполняем команду (Модуль A)
2. Периодически выполняем запрос (Модуль B)
3. Ждём, пока результат появится
4. Делаем assert
Пример:
var userId = await Sender.Send(new RegisterUserCommand(...));
var result = await Poller.WaitAsync(
TimeSpan.FromSeconds(15),
async () =>
{
return await Sender.Send(new GetCustomerQuery(userId));
});
result.Should().NotBeNull();
result.IsSuccess.Should().BeTrue();MigrationsHistoryTable.
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
connectionString,
sqlOptions =>
{
sqlOptions.MigrationsHistoryTable(
tableName: "MigrationHistory",
schema: "infrastructure"
);
}));
// Теперь EF будет хранить историю миграций в:
// infrastructure.MigrationHistory