День 1274. #ЧтоНовенького
Обновления ASP.NET Core в .NET 7 Превью 6. Окончание
Начало
6. Поддержка регистрации дополнительных заголовков запросов в W3CLogger
W3Clogger – логгер, который пишет лог-файлы в формате стандарта W3C.
Теперь вы можете указать дополнительные заголовки запросов
В Blazor появились два новых шаблона проектов для старта «с чистого листа». Новые шаблоны такие же, как их непустые аналоги, но без дополнительного демонстрационного кода, только с очень простой домашней страницей. Также удалён Bootstrap, чтобы можно было использовать любой CSS-фреймворк.
Новые шаблоны доступны в Visual Studio после установки пакета SDK для .NET 7, а также из командной строки:
.NET 6 поддерживал семейство алгоритмов хеширования SHA при работе на WebAssembly. .NET 7 позволяет использовать больше криптографических алгоритмов, используя преимущества SubtleCrypto, когда это возможно, и возвращаясь к реализации .NET, когда SubtleCrypto использовать нельзя. Теперь поддерживаются следующие алгоритмы:
- SHA1
- SHA256
- SHA384
- SHA512
- HMACSHA1
- HMACSHA256
- HMACSHA384
- HMACSHA512
Поддержка AES-CBC, PBKDF2 и HKDF запланирована в будущих обновлениях .NET 7.
9. Поддержка пользовательских элементов Blazor больше не является экспериментальной
Ранее экспериментальный пакет Microsoft.AspNetCore.Components.CustomElements для создания пользовательских элементов Blazor на основе стандартных больше не является экспериментальным и теперь является частью выпуска .NET 7. Подробности см. в документации о создании пользовательских элементов Blazor.
10. Экспериментальный компонент QuickGrid для Blazor
QuickGrid — это новый экспериментальный компонент Blazor для быстрого и эффективного отображения данных в табличной форме. QuickGrid предоставляет простой и удобный компонент сетки данных для наиболее распространённых случаев. Чтобы использовать компонент, добавьте пакет
Microsoft.AspNetCore.Components.QuickGrid. Примеры использования можно посмотреть здесь.
Источник: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-6/
Обновления ASP.NET Core в .NET 7 Превью 6. Окончание
Начало
6. Поддержка регистрации дополнительных заголовков запросов в W3CLogger
W3Clogger – логгер, который пишет лог-файлы в формате стандарта W3C.
Теперь вы можете указать дополнительные заголовки запросов
AdditionalRequestHeaders()
в W3CLoggerOptions
:services.AddW3CLogging(l =>7. Пустые шаблоны проектов Blazor
{
l.AdditionalRequestHeaders.Add("x-forwarded-for");
l.AdditionalRequestHeaders.Add("x-client-ssl-protocol");
});
В Blazor появились два новых шаблона проектов для старта «с чистого листа». Новые шаблоны такие же, как их непустые аналоги, но без дополнительного демонстрационного кода, только с очень простой домашней страницей. Также удалён Bootstrap, чтобы можно было использовать любой CSS-фреймворк.
Новые шаблоны доступны в Visual Studio после установки пакета SDK для .NET 7, а также из командной строки:
dotnet new blazorserver-empty8. Поддержка System.Security.Cryptography в WebAssembly
dotnet new blazorwasm-empty
.NET 6 поддерживал семейство алгоритмов хеширования SHA при работе на WebAssembly. .NET 7 позволяет использовать больше криптографических алгоритмов, используя преимущества SubtleCrypto, когда это возможно, и возвращаясь к реализации .NET, когда SubtleCrypto использовать нельзя. Теперь поддерживаются следующие алгоритмы:
- SHA1
- SHA256
- SHA384
- SHA512
- HMACSHA1
- HMACSHA256
- HMACSHA384
- HMACSHA512
Поддержка AES-CBC, PBKDF2 и HKDF запланирована в будущих обновлениях .NET 7.
9. Поддержка пользовательских элементов Blazor больше не является экспериментальной
Ранее экспериментальный пакет Microsoft.AspNetCore.Components.CustomElements для создания пользовательских элементов Blazor на основе стандартных больше не является экспериментальным и теперь является частью выпуска .NET 7. Подробности см. в документации о создании пользовательских элементов Blazor.
10. Экспериментальный компонент QuickGrid для Blazor
QuickGrid — это новый экспериментальный компонент Blazor для быстрого и эффективного отображения данных в табличной форме. QuickGrid предоставляет простой и удобный компонент сетки данных для наиболее распространённых случаев. Чтобы использовать компонент, добавьте пакет
Microsoft.AspNetCore.Components.QuickGrid. Примеры использования можно посмотреть здесь.
Источник: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-6/
👍10
День 1275. #ЗаметкиНаПолях
Настройка Через Параметры Командной Строки в Консольных Приложениях
Внедрение зависимостей значительно упрощает управление ресурсами в приложениях .NET, по крайней мере, если вы разберётесь с настройкой хоста.
Для приложений .NET мы обычно используем файл JSON с настройками, но можно сделать приложение более гибким, с помощью параметров командной строки. Вариантом использования может быть временное решение, которое требуется запускать как запланированное задание.
В примере ниже консольное приложение .NET вызывается в терминале, а параметры являются позиционными и все обязательные. Приложение вызывается так:
Важно отметить, что в нашей конфигурации хоста мы сопоставляем параметры с элементами словаря, а в классе извлекаем настроенные значения, как и в любом другом случае использования интерфейса
Полный код примера здесь
Источник: https://dev.to/alfetta159/configuration-using-command-line-parameters-in-net-console-applications-21e4
Настройка Через Параметры Командной Строки в Консольных Приложениях
Внедрение зависимостей значительно упрощает управление ресурсами в приложениях .NET, по крайней мере, если вы разберётесь с настройкой хоста.
Для приложений .NET мы обычно используем файл JSON с настройками, но можно сделать приложение более гибким, с помощью параметров командной строки. Вариантом использования может быть временное решение, которое требуется запускать как запланированное задание.
В примере ниже консольное приложение .NET вызывается в терминале, а параметры являются позиционными и все обязательные. Приложение вызывается так:
dotnet MyApp.dll first second third fourth fifthТеперь проведём настройку хоста в файле program.cs, сначала создавая построитель по умолчанию с аргументами командной строки, а затем настраиваем конфигурацию приложения как коллекцию в памяти, основанную на парах ключ-значение из словаря:
using IHost host = HostТеперь мы можем передать эту конфигурацию как параметр в любой конструктор:
.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((_, conf) =>
conf.AddInMemoryCollection(
new Dictionary<string, string> {
["First"] = args[0],
["Second"] = args[1],
["Third"] = args[2],
["Fourth"] = args[3],
["Fifth"] = args[4]
}))
.ConfigureServices((_, srvc) =>
srvc.AddScoped<TestClass>())
.Build();
using System.Text;И далее вызвать класс как сервис:
using Microsoft.Extensions.Configuration;
namespace MyApp;
public class TestClass
{
private readonly string First;
private readonly string Second;
private readonly string Third;
private readonly string Fourth;
private readonly string Fifth;
public TestClass(IConfiguration conf)
{
First = conf["First"];
Second = conf["Second"];
Third = conf["Third"];
Fourth = conf["Fourth"];
Fifth = conf["Fifth"];
}
public void Run()
{
//…
}
}
var test = host.Services.GetService<TestClass>();Этот пример не проверяет список параметров и не предлагает какой-либо гибкости. Здесь мы просто превращаем параметры командной строки в удобную конфигурацию, передаваемую через внедрение зависимостей.
test.Run();
Важно отметить, что в нашей конфигурации хоста мы сопоставляем параметры с элементами словаря, а в классе извлекаем настроенные значения, как и в любом другом случае использования интерфейса
IConfiguration
.Полный код примера здесь
Источник: https://dev.to/alfetta159/configuration-using-command-line-parameters-in-net-console-applications-21e4
👍1
День 1276. #Карьера
Что Можно Делать Перед Работой, Чтобы Улучшить Ментальное Состояние и Повысить Продуктивность
По возможности не стоит вставать с кровати и сразу же отправляться на работу. Эксперты говорят, что стоит добавить в ежедневный распорядок занятия собой перед работой.
«Осознаёте вы это или нет, старт рабочего дня в плохом настроении может сильно испортить весь день», - говорит Джоэл Двоскин, психолог из Медицинского колледжа Университета Аризоны. Хорошо, что обратное также справедливо. «Просто размышление о том, что вы сегодня можете сделать для себя, перед началом рабочего дня может повлиять на ваше удовлетворение от работы, продуктивность и на то, как вы работаете с коллегами».
Перед работой вы можете заняться множеством дел, чтобы проверить свой ментальный статус, улучшить настроение и повысить эффективность работы. Вот три пути, по мнению экспертов:
1. Проведите время в тихой обстановке
Практика «настройки сознания» может быть очень полезной для вашей продуктивности. Смысл в том, чтобы выделить первые 20–30 минут утра для уединения. В это время обратите внимание на ваши желания и стремления,
подумайте о том, чего вы хотели бы достичь в течение дня. Вот некоторые из вопросов, которые стоит задать себе:
- Что меня волнует сегодня?
- Что действительно важно для меня в перспективе?
- Чего стоит сегодня добиться?
- Что будет успехом?
2. Займитесь физической активностью
Найдите свой любимый способ подвигаться и стремитесь делать это всякий раз, прежде чем браться за работу. Простая прогулка по пять минут в день рядом с вашим домом может стать отличным началом.
«Есть исследования, которые показывают, что движение может помочь людям сосредоточиться и успокоиться», — говорит Двоскин. Согласно сводному обзору более 1000 исследований, проведённых с 1990 по 2020 год, движение в любой форме положительно влияет на самочувствие и уменьшает симптомы депрессии по сравнению с полным отсутствием физических упражнений. Если найти свободное время каждый день сложно, есть альтернативы. Даже просто выйти на балкон или во двор и потянуться пару минут будет полезно.
3. Побалуйте себя
Это сугубо индивидуальное занятие, но заняться тем, что вы любите, или побаловать себя чем-то, что вам нравится, может стать зарядом позитивной энергии для отличного рабочего дня.
Мы чувствуем, что наша жизнь не принадлежит нам по утрам, поэтому переключаем будильник и остаёмся в кровати подольше, пытаясь удержать каждую минуту, которую мы можем сохранить для себя. Нужно найти какое-нибудь утреннее занятие, которое вам действительно интересно и которого вы с нетерпением ждёте:
- Приготовьте свой любимый завтрак,
- Включите любимый плейлист, пока собираетесь,
- Возьмите побольше стакан вашего любимого напитка в кофейне,
- Посмотрите эпизод сериала, который вам нравится.
Независимо от того, как вы это сделаете, важно выделить время для себя утром. Личное развитие и внимание к своему ментальному здоровью являются частью профессионального развития. Если вы заботитесь о себе в личное время, это сделает вас более эффективным в профессиональное время.
Источник: https://www.cnbc.com/2022/07/26/3-activities-before-work-that-improve-mental-health-and-productivity.html
Что Можно Делать Перед Работой, Чтобы Улучшить Ментальное Состояние и Повысить Продуктивность
По возможности не стоит вставать с кровати и сразу же отправляться на работу. Эксперты говорят, что стоит добавить в ежедневный распорядок занятия собой перед работой.
«Осознаёте вы это или нет, старт рабочего дня в плохом настроении может сильно испортить весь день», - говорит Джоэл Двоскин, психолог из Медицинского колледжа Университета Аризоны. Хорошо, что обратное также справедливо. «Просто размышление о том, что вы сегодня можете сделать для себя, перед началом рабочего дня может повлиять на ваше удовлетворение от работы, продуктивность и на то, как вы работаете с коллегами».
Перед работой вы можете заняться множеством дел, чтобы проверить свой ментальный статус, улучшить настроение и повысить эффективность работы. Вот три пути, по мнению экспертов:
1. Проведите время в тихой обстановке
Практика «настройки сознания» может быть очень полезной для вашей продуктивности. Смысл в том, чтобы выделить первые 20–30 минут утра для уединения. В это время обратите внимание на ваши желания и стремления,
подумайте о том, чего вы хотели бы достичь в течение дня. Вот некоторые из вопросов, которые стоит задать себе:
- Что меня волнует сегодня?
- Что действительно важно для меня в перспективе?
- Чего стоит сегодня добиться?
- Что будет успехом?
2. Займитесь физической активностью
Найдите свой любимый способ подвигаться и стремитесь делать это всякий раз, прежде чем браться за работу. Простая прогулка по пять минут в день рядом с вашим домом может стать отличным началом.
«Есть исследования, которые показывают, что движение может помочь людям сосредоточиться и успокоиться», — говорит Двоскин. Согласно сводному обзору более 1000 исследований, проведённых с 1990 по 2020 год, движение в любой форме положительно влияет на самочувствие и уменьшает симптомы депрессии по сравнению с полным отсутствием физических упражнений. Если найти свободное время каждый день сложно, есть альтернативы. Даже просто выйти на балкон или во двор и потянуться пару минут будет полезно.
3. Побалуйте себя
Это сугубо индивидуальное занятие, но заняться тем, что вы любите, или побаловать себя чем-то, что вам нравится, может стать зарядом позитивной энергии для отличного рабочего дня.
Мы чувствуем, что наша жизнь не принадлежит нам по утрам, поэтому переключаем будильник и остаёмся в кровати подольше, пытаясь удержать каждую минуту, которую мы можем сохранить для себя. Нужно найти какое-нибудь утреннее занятие, которое вам действительно интересно и которого вы с нетерпением ждёте:
- Приготовьте свой любимый завтрак,
- Включите любимый плейлист, пока собираетесь,
- Возьмите побольше стакан вашего любимого напитка в кофейне,
- Посмотрите эпизод сериала, который вам нравится.
Независимо от того, как вы это сделаете, важно выделить время для себя утром. Личное развитие и внимание к своему ментальному здоровью являются частью профессионального развития. Если вы заботитесь о себе в личное время, это сделает вас более эффективным в профессиональное время.
Источник: https://www.cnbc.com/2022/07/26/3-activities-before-work-that-improve-mental-health-and-productivity.html
👍11
День 1278. #Безопасность
Атаки на Отказ в Обслуживании с помощью Регулярных Выражений (ReDoS)
Регулярные выражения сложно оценивать. Неправильный шаблон может привести к низкой производительности, ошибочным результатам и даже к уязвимости.
Плохо спроектированные шаблоны регулярных выражений могут привести к неудачной проверке входных данных, негерметичным брандмауэрам и даже атакам на отказ в обслуживании (DoS). При DoS-атаке злоумышленник замедляет работу онлайн-сервиса или делает его недоступным для пользователей. Существует множество различных типов DoS, одним из которых является ReDoS, когда злоумышленник предоставляет механизму регулярных выражений строку, для оценки которой требуется много времени с помощью так называемых «злых шаблонов» (evil regex).
Большинство оценщиков регулярных выражений имеют экспоненциальную сложность в худшем случае, т.е. время оценки растёт экспоненциально по отношению к размеру входной строки. Шаблоны, которые могут привести к зависанию приложения при оценке, имеют две характеристики:
1) часто включают повторение сложных подвыражений (
2) внутри этих повторяющихся подвыражений есть дополнительные повторяющиеся символы и выражения, которые соответствуют суффиксу другого совпадения.
Например:
Иногда приложения позволяют пользователям вводить собственные шаблоны регулярных выражений для выполнения сервером. В этом случае злоумышленник может внедрить вредоносное регулярное выражение по своему выбору, а затем отправить строку ввода, которая заставит злонамеренное регулярное выражение выполняться в течение длительного времени.
Другой пример - при регистрации проверка, содержит ли пароль пользователя его имя. Если приложение вслепую использует имя пользователя как шаблон без очистки спецсимволов, например:
1. Многопоточность и упреждающее уничтожение процессов. Многопоточное приложение может одновременно обрабатывать другие запросы, даже если вычисление регулярного выражения занимает слишком много времени. Также нужно останавливать выполнение любой оценки регулярного выражения, если она занимает больше времени, чем ожидалось.
2. Не стоит раскрывать ваши шаблоны регулярных выражений. Иногда они публикуются, потому что проект имеет открытый исходный код, или случайно, т.к. используются одни и те же шаблоны как в серверном, так и в клиентском коде. Это облегчает злоумышленникам поиск вредоносных регулярных выражений и создание соответствующих строк для атаки.
3. Избегайте использования опасных регулярных выражений для оценки пользовательского ввода (см. критерии выше) и вместо этого используйте более простые. Поищите проверенные и защищённые шаблоны вместо того, чтобы писать свои собственные.
4. Исключите возможность для пользователей предоставлять свои шаблоны регулярных выражений оценщику. Если вам нужна такая функциональность, используйте предварительно отформатированные регулярные выражения, которые допускают минимальную настройку.
Источник: https://sec.okta.com/articles/2020/04/attacking-evil-regex-understanding-regular-expression-denial-service
Атаки на Отказ в Обслуживании с помощью Регулярных Выражений (ReDoS)
Регулярные выражения сложно оценивать. Неправильный шаблон может привести к низкой производительности, ошибочным результатам и даже к уязвимости.
Плохо спроектированные шаблоны регулярных выражений могут привести к неудачной проверке входных данных, негерметичным брандмауэрам и даже атакам на отказ в обслуживании (DoS). При DoS-атаке злоумышленник замедляет работу онлайн-сервиса или делает его недоступным для пользователей. Существует множество различных типов DoS, одним из которых является ReDoS, когда злоумышленник предоставляет механизму регулярных выражений строку, для оценки которой требуется много времени с помощью так называемых «злых шаблонов» (evil regex).
Большинство оценщиков регулярных выражений имеют экспоненциальную сложность в худшем случае, т.е. время оценки растёт экспоненциально по отношению к размеру входной строки. Шаблоны, которые могут привести к зависанию приложения при оценке, имеют две характеристики:
1) часто включают повторение сложных подвыражений (
+
и *
в сложных подвыражениях),2) внутри этих повторяющихся подвыражений есть дополнительные повторяющиеся символы и выражения, которые соответствуют суффиксу другого совпадения.
Например:
^(a+)+$Подвыражение в скобках ищет повторяющийся символ «a». Оно также проверяет, является ли всё выражение повторением какого-либо из подвыражений! Допустим, злоумышленник вводит такие данные:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaЗдесь каждая дополнительная буква "a" заставит оценщик проверять наличие повторений дополнительного подвыражения, таким образом удваивая количество времени обработки.
Иногда приложения позволяют пользователям вводить собственные шаблоны регулярных выражений для выполнения сервером. В этом случае злоумышленник может внедрить вредоносное регулярное выражение по своему выбору, а затем отправить строку ввода, которая заставит злонамеренное регулярное выражение выполняться в течение длительного времени.
Другой пример - при регистрации проверка, содержит ли пароль пользователя его имя. Если приложение вслепую использует имя пользователя как шаблон без очистки спецсимволов, например:
var r = new Regex(username, RegexOptions.IgnoreCase);Тогда злоумышленник может внедрить вредоносное регулярное выражение через поле имени пользователя:
var result = r.Match(password);
username: ^(a+)+$Способы борьбы с ReDoS:
password: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1. Многопоточность и упреждающее уничтожение процессов. Многопоточное приложение может одновременно обрабатывать другие запросы, даже если вычисление регулярного выражения занимает слишком много времени. Также нужно останавливать выполнение любой оценки регулярного выражения, если она занимает больше времени, чем ожидалось.
2. Не стоит раскрывать ваши шаблоны регулярных выражений. Иногда они публикуются, потому что проект имеет открытый исходный код, или случайно, т.к. используются одни и те же шаблоны как в серверном, так и в клиентском коде. Это облегчает злоумышленникам поиск вредоносных регулярных выражений и создание соответствующих строк для атаки.
3. Избегайте использования опасных регулярных выражений для оценки пользовательского ввода (см. критерии выше) и вместо этого используйте более простые. Поищите проверенные и защищённые шаблоны вместо того, чтобы писать свои собственные.
4. Исключите возможность для пользователей предоставлять свои шаблоны регулярных выражений оценщику. Если вам нужна такая функциональность, используйте предварительно отформатированные регулярные выражения, которые допускают минимальную настройку.
Источник: https://sec.okta.com/articles/2020/04/attacking-evil-regex-understanding-regular-expression-denial-service
👍16
День 1279. #ЗаметкиНаПолях #AsyncTips
Связанные Запросы на Отмену
Подробнее про токены отмены см. «Скоординированная отмена».
Задача: в коде присутствует промежуточный уровень, который должен реагировать на запросы на отмену «сверху», а также выдавать собственные запросы на отмену на следующий уровень.
Решение
В .NET предусмотрена встроенная поддержка этого сценария в виде связанных токенов отмены. Источник токена отмены может быть создан связанным с одним (или несколькими) существующими токенами. Когда вы создаёте источник связанного токена отмены, полученный токен будет отменяться как при непосредственной отмене его, так и при отмене любого из связанных токенов.
Следующий пример выполняет асинхронный запрос HTTP. Токен
Хотя в примере выше используется только один токен
Например, ASP.NET предоставляет токен отмены, представляющий отключение пользователя. Код обработчика может создать связанный токен, который реагирует либо на отключение пользователя, либо на свои причины отмены (например, тайм-аут).
Помните о сроке существования источника связанного токена отмены. Предыдущий пример является наиболее типичным: один или несколько токенов отмены передаются методу, который связывает их и передаёт как комбинированный токен. Обратите внимание на то, что в примере используется команда using, которая гарантирует, что источник связанного токена отмены будет освобожден, когда операция будет завершена (а комбинированный токен перестанет использоваться). Подумайте, что произойдёт, если код не освободит источник связанного токена отмены: может оказаться, что метод
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
Связанные Запросы на Отмену
Подробнее про токены отмены см. «Скоординированная отмена».
Задача: в коде присутствует промежуточный уровень, который должен реагировать на запросы на отмену «сверху», а также выдавать собственные запросы на отмену на следующий уровень.
Решение
В .NET предусмотрена встроенная поддержка этого сценария в виде связанных токенов отмены. Источник токена отмены может быть создан связанным с одним (или несколькими) существующими токенами. Когда вы создаёте источник связанного токена отмены, полученный токен будет отменяться как при непосредственной отмене его, так и при отмене любого из связанных токенов.
Следующий пример выполняет асинхронный запрос HTTP. Токен
ct
, переданный методу GetWithTimeoutAsync
, представляет отмену, запрошенную конечным пользователем, а сам метод также применяет тайм-аут к запросу:async Task<HttpResponseMessage>Полученный токен
GetWithTimeoutAsync(
HttpClient client,
string url,
CancellationToken ct)
{
using var cts =
CancellationTokenSource
.CreateLinkedTokenSource(ct);
cts.CancelAfter(TimeSpan.FromSeconds(2));
var combinedToken = cts.Token;
return await client.GetAsync(url, combinedToken);
}
combinedToken
отменяется либо когда пользователь отменяет существующий токен ct
, либо при отмене связанного источника вызовом CancelAfter
.Хотя в примере выше используется только один токен
ct
, метод CreateLinkedTokenSource
может получать любое количество токенов отмены в своих параметрах. Это позволяет вам создать один объединённый токен, на базе которого можно реализовать собственную логику отмены. Например, ASP.NET предоставляет токен отмены, представляющий отключение пользователя. Код обработчика может создать связанный токен, который реагирует либо на отключение пользователя, либо на свои причины отмены (например, тайм-аут).
Помните о сроке существования источника связанного токена отмены. Предыдущий пример является наиболее типичным: один или несколько токенов отмены передаются методу, который связывает их и передаёт как комбинированный токен. Обратите внимание на то, что в примере используется команда using, которая гарантирует, что источник связанного токена отмены будет освобожден, когда операция будет завершена (а комбинированный токен перестанет использоваться). Подумайте, что произойдёт, если код не освободит источник связанного токена отмены: может оказаться, что метод
GetWithTimeoutAsync
будет вызван несколько раз с одним (долгосрочным) существующим токеном; в этом случае код будет создавать новый источник связанного токена при каждом вызове. Даже после того, как запросы HTTP завершатся (и ничто не будет использовать комбинированный токен), эти связанные источники будут оставаться присоединенными к существующему токену. Чтобы предотвратить подобные утечки памяти, освобождайте источник связанного токена отмены, когда комбинированный токен перестаёт быть нужным.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
👍4
Архитектура Rider и не только
DotNet & More
День 1280. #Подкаст
Сегодня предложу вам посмотреть/послушать эпизод подкаста DotNet&More #70: Архитектура Rider и не только. На чём написан Rider и другие продукты JetBrains? Кто работает над продуктом? Как команды справляются с объёмом кода? Чем разработка IDE отличается от обычной Enterprise разработки? В продолжение обсуждения вчерашнего квиза про то, зачем знать какие классы реализуют какие интерфейсы, ребята обсуждают, что нужно знать кандидату при устройстве в JetBrains, и чем требования отличаются от требований в обычных компаниях.
Честно признаюсь, я процентов 20 из того, что авторы обсуждали, не понял совсем. Это для меня какие-то высшие материи. Но всё равно интересно.
Можете посмотреть эпизод на ютуб, либо (надеюсь, ребята не обидятся на меня) послушать его прямо здесь.
Источник: https://t.iss.one/dotnetmore
Сегодня предложу вам посмотреть/послушать эпизод подкаста DotNet&More #70: Архитектура Rider и не только. На чём написан Rider и другие продукты JetBrains? Кто работает над продуктом? Как команды справляются с объёмом кода? Чем разработка IDE отличается от обычной Enterprise разработки? В продолжение обсуждения вчерашнего квиза про то, зачем знать какие классы реализуют какие интерфейсы, ребята обсуждают, что нужно знать кандидату при устройстве в JetBrains, и чем требования отличаются от требований в обычных компаниях.
Честно признаюсь, я процентов 20 из того, что авторы обсуждали, не понял совсем. Это для меня какие-то высшие материи. Но всё равно интересно.
Можете посмотреть эпизод на ютуб, либо (надеюсь, ребята не обидятся на меня) послушать его прямо здесь.
Источник: https://t.iss.one/dotnetmore
👍9👎2
День 1281. #ЧтоНовенького
Microsoft Прекратит Поддержку .NET Core 3.1
Долгосрочная поддержка (LTS) версии 3.1 Microsoft .NET Core Framework должна прекратиться 13 декабря 2022г. Microsoft рекомендует обновить приложения .NET Core 3.1 до .NET 6.0, чтобы поддерживать их в будущем. Однако у разработчиков неоднозначное отношение к политике поддержки .NET.
По словам Доминика Уиттакера, старшего менеджера программ в Microsoft, клиентам, использующим версию 3.1, следует перейти на .NET 6 или 7, чтобы по-прежнему получать официальную поддержку и исправления безопасности. Уиттакер объясняет, что приложения .NET Core 3.1 по-прежнему будут работать после окончания поддержки, но клиенты могут столкнуться с потенциальными недостатками безопасности, которые будут исправляться только для поддерживаемых версий.
Версия 3.1 — это то, что Microsoft называет выпуском с долгосрочной поддержкой (LTS), жизненный цикл поддержки которого составляет три года с даты выпуска. Текущие (не LTS) выпуски, такие как .NET 7.0, имеют более короткий жизненный цикл поддержки 18 месяцев, т.е. Microsoft будет поддерживать их в течение шести месяцев после выпуска следующей LTS версии.
Последней LTS-версией .NET является 6.0, которую Microsoft планирует поддерживать до 12 ноября 2024 года. В ноябре 2022 года планируется выпуск .NET 7.0 (не LTS версии), т.е. текущие клиенты .NET Core 3.1 могут выбрать между обновлением до .NET 6 или 7.
Обновление до .NET 6.0 включает изменение одной строки в файле проекта для изменения версии целевой платформы. Однако между .NET Core 3.1 и .NET 6.0 могут быть несовместимости среды выполнения или исходного кода.
Microsoft рекомендует разработчикам просмотреть официальное руководство по совместимости на наличие проблем при обновлении своих приложений и предоставляет инструмент обновления с открытым исходным кодом под названием upgrade-assistant. Инструмент анализирует код приложения, обновляет файлы проекта, проверяет наличие критических изменений и выполняет некоторые автоматические исправления кода, но разработчикам всё равно придётся делать некоторые исправления вручную.
Реакция сообщества разработчиков в социальных сетях была неоднозначной. Некоторые утверждают, что трёхлетний цикл поддержки слишком короток для корпоративных проектов, в то время как другие признают, что растущая сложность зависимостей кода делает частые обновления версий необходимостью и новым способом работы. Рокфорд Лхотка, создатель широко используемой среды приложений CSLA .NET, объясняет, что большая часть проблем при обновлении кода .NET связана с переходом от старой .NET Framework на современную инфраструктуру .NET, в то время как обновления между версиями .NET Core существенно менее трудоёмки.
Майкрософт регулярно публикует сводные данные об использовании .NET SDK. По данным на июнь 2022 года, наиболее используемой версией является именно .NET Core 3.1, на которую приходится 31%.
Источник: https://www.infoq.com/news/2022/07/microsoft-dotnet/
Microsoft Прекратит Поддержку .NET Core 3.1
Долгосрочная поддержка (LTS) версии 3.1 Microsoft .NET Core Framework должна прекратиться 13 декабря 2022г. Microsoft рекомендует обновить приложения .NET Core 3.1 до .NET 6.0, чтобы поддерживать их в будущем. Однако у разработчиков неоднозначное отношение к политике поддержки .NET.
По словам Доминика Уиттакера, старшего менеджера программ в Microsoft, клиентам, использующим версию 3.1, следует перейти на .NET 6 или 7, чтобы по-прежнему получать официальную поддержку и исправления безопасности. Уиттакер объясняет, что приложения .NET Core 3.1 по-прежнему будут работать после окончания поддержки, но клиенты могут столкнуться с потенциальными недостатками безопасности, которые будут исправляться только для поддерживаемых версий.
Версия 3.1 — это то, что Microsoft называет выпуском с долгосрочной поддержкой (LTS), жизненный цикл поддержки которого составляет три года с даты выпуска. Текущие (не LTS) выпуски, такие как .NET 7.0, имеют более короткий жизненный цикл поддержки 18 месяцев, т.е. Microsoft будет поддерживать их в течение шести месяцев после выпуска следующей LTS версии.
Последней LTS-версией .NET является 6.0, которую Microsoft планирует поддерживать до 12 ноября 2024 года. В ноябре 2022 года планируется выпуск .NET 7.0 (не LTS версии), т.е. текущие клиенты .NET Core 3.1 могут выбрать между обновлением до .NET 6 или 7.
Обновление до .NET 6.0 включает изменение одной строки в файле проекта для изменения версии целевой платформы. Однако между .NET Core 3.1 и .NET 6.0 могут быть несовместимости среды выполнения или исходного кода.
Microsoft рекомендует разработчикам просмотреть официальное руководство по совместимости на наличие проблем при обновлении своих приложений и предоставляет инструмент обновления с открытым исходным кодом под названием upgrade-assistant. Инструмент анализирует код приложения, обновляет файлы проекта, проверяет наличие критических изменений и выполняет некоторые автоматические исправления кода, но разработчикам всё равно придётся делать некоторые исправления вручную.
Реакция сообщества разработчиков в социальных сетях была неоднозначной. Некоторые утверждают, что трёхлетний цикл поддержки слишком короток для корпоративных проектов, в то время как другие признают, что растущая сложность зависимостей кода делает частые обновления версий необходимостью и новым способом работы. Рокфорд Лхотка, создатель широко используемой среды приложений CSLA .NET, объясняет, что большая часть проблем при обновлении кода .NET связана с переходом от старой .NET Framework на современную инфраструктуру .NET, в то время как обновления между версиями .NET Core существенно менее трудоёмки.
Майкрософт регулярно публикует сводные данные об использовании .NET SDK. По данным на июнь 2022 года, наиболее используемой версией является именно .NET Core 3.1, на которую приходится 31%.
Источник: https://www.infoq.com/news/2022/07/microsoft-dotnet/
👍9
День 1282. #ЗаметкиНаПолях
Исправляем Отсутствующий Источник Пакетов NuGet
Иногда после настройки системы с нуля, установки Visual Studio и создания нового проекта при сборке проекта может возникать ошибка NU1101, говорящая о том, что восстановление пакета не удалось. Например:
NU1101 Unable to find package Swashbuckle.AspNetCore. No packages exist with this id in source(s): Microsoft Visual Studio Offline Packages
В настройках менеджера пакетов NuGet во вкладке Package Sources (Источники Пакетов) при этом будет отсутствовать источник по умолчанию Nuget.org.
Как это исправить?
Существует три файла конфигурации NuGet.Config доступные для Visual Studio, которые можно использовать для управления источниками NuGet:
1. Файл конфигурации, локальный для проекта или решения. Размещается соответственно в папке проекта или решения.
2. Файл конфигурации для конкретного пользователя для всех проектов пользователя. Размещение:
- в Windows:
- в Mac/Linux:
3. Общесистемная конфигурация, влияющая на всех пользователей на компьютере. Размещение:
- в Windows:
- в Mac/Linux:
Эти файлы конфигурации применяются иерархически. Источники, специфичные для проекта, переопределяют конфигурацию пользователя, а настройки пользователя, переопределяют общесистемные.
Собственно, в файл в раздел
Источник: https://blog.nimblepros.com/blogs/fix-missing-default-nuget-feed/
Исправляем Отсутствующий Источник Пакетов NuGet
Иногда после настройки системы с нуля, установки Visual Studio и создания нового проекта при сборке проекта может возникать ошибка NU1101, говорящая о том, что восстановление пакета не удалось. Например:
NU1101 Unable to find package Swashbuckle.AspNetCore. No packages exist with this id in source(s): Microsoft Visual Studio Offline Packages
В настройках менеджера пакетов NuGet во вкладке Package Sources (Источники Пакетов) при этом будет отсутствовать источник по умолчанию Nuget.org.
Как это исправить?
Существует три файла конфигурации NuGet.Config доступные для Visual Studio, которые можно использовать для управления источниками NuGet:
1. Файл конфигурации, локальный для проекта или решения. Размещается соответственно в папке проекта или решения.
2. Файл конфигурации для конкретного пользователя для всех проектов пользователя. Размещение:
- в Windows:
%appdata%\NuGet\NuGet.Config
,- в Mac/Linux:
~/.config/NuGet/NuGet.Config
либо ~/.nuget/NuGet/NuGet.Config
(по-разному в разных дистрибутивах).3. Общесистемная конфигурация, влияющая на всех пользователей на компьютере. Размещение:
- в Windows:
%ProgramFiles(x86)%\NuGet\Config
,- в Mac/Linux:
$XDG_DATA_HOME
. Если $XDG_DATA_HOME
пустой, ~/.local/share
либо /usr/local/share
(по-разному в разных дистрибутивах).Эти файлы конфигурации применяются иерархически. Источники, специфичные для проекта, переопределяют конфигурацию пользователя, а настройки пользователя, переопределяют общесистемные.
Собственно, в файл в раздел
packageSources
нужно добавить строку со ссылкой на api.nuget.org
, как показано ниже:<?xml version="1.0" encoding="utf-8"?>После изменения файла перезапустите Visual Studio и пересоберите решение. Нужные пакеты NuGet теперь должны восстановиться из указанного источника.
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
Источник: https://blog.nimblepros.com/blogs/fix-missing-default-nuget-feed/
👍9
День 1283. #Testing
Playwright Trace Viewer
Начало: E2E-тесты с Помощью Playwright
Огромным преимуществом использования автоматизированного запуска E2E-тестов, является возможность записывать видео и делать скриншоты всех ваших тестовых прогонов прямо из коробки. Playwright пока не может записывать видео, но может делать скриншоты каждого шага, до и после него, и это обеспечивает отличную возможность просмотра тестового прогона, чтобы точно определить, что пошло не так. Для этого требуется небольшая настройка.
Используем пример из предыдущего поста, в котором используется MSTest, и немного расширим его. Для других тестовых систем код аналогичен. В класс тестов нужно добавить методы инициализации и очистки теста. Для MSTest они выглядят так:
В папке bin теперь будет zip-файл для каждого нашего теста. Допустим, наш тест не прошёл. Полученный zip-файл можно просмотреть в инструменте просмотра трассировки на https://trace.playwright.dev/
На картинке ниже в верхней части страницы у нас временная шкала прохождения теста и скриншоты для каждого периода времени. Цветами выделены различные события, поэтому мы можем сразу перейти к определённому моменту в нашем тесте. Слева список выполненных шагов, можно щёлкнуть на шаг, чтобы перейти на соответствующее место на временной шкале.
В центре страницы находится наш скриншот. Но что важно, мы можем переключать вкладки для представления «До» (Before) и «После» (After). Это безумно удобно при вводе текста или при заполнении других полей ввода. Представьте, что тест пытается заполнить очень большую форму, и на самом первом шаге он неправильно заполняет текстовое поле. Тест потерпит неудачу только при отправке формы и проверке данных, но на скриншоте в моменте возникновения ошибки мы можем даже не увидеть само текстовое поле. Playwright даёт нам пошаговое представление о каждом шаге теста, происходящем по мере его прохождения.
Справа есть куча отладочной информации, включая отладочный вывод Playwright, консольный вывод браузера, сетевой вывод браузера (аналогично инструментам разработчика Chrome/Firefox), а также исходный код нашего текста с выделенным текущим шагом.
Это невероятно полезно. Если тест терпит неудачу, мы можем точно знать, где в нашем коде он был и что пытался сделать.
Источник: https://dotnetcoretutorials.com/2022/05/20/using-playwright-e2e-tests-with-c-net/
Playwright Trace Viewer
Начало: E2E-тесты с Помощью Playwright
Огромным преимуществом использования автоматизированного запуска E2E-тестов, является возможность записывать видео и делать скриншоты всех ваших тестовых прогонов прямо из коробки. Playwright пока не может записывать видео, но может делать скриншоты каждого шага, до и после него, и это обеспечивает отличную возможность просмотра тестового прогона, чтобы точно определить, что пошло не так. Для этого требуется небольшая настройка.
Используем пример из предыдущего поста, в котором используется MSTest, и немного расширим его. Для других тестовых систем код аналогичен. В класс тестов нужно добавить методы инициализации и очистки теста. Для MSTest они выглядят так:
[TestInitialize]Метод
public async Task TestSetup()
{
await Context.Tracing.StartAsync(
new TracingStartOptions {
Title = TestContext.TestName,
Screenshots = true,
Snapshots = true,
Sources = true
}
);
}
[TestCleanup]
public async Task TestCleanup()
{
await Context.Tracing.StopAsync(
new TracingStopOptions {
Path = TestContext.TestName + ".zip"
}
);
}
TestInitialize
запускает для нас трассировку. Объект TestContext
— это специальный класс MSTest, который может сообщить нам, какой тест выполняется, вы можете заменить его на аналогичный класс в другой тестовой среде или просто поместить сюда любую строку.TestCleanup
завершает трассировку, сохраняя результаты в ZIP-файле.В папке bin теперь будет zip-файл для каждого нашего теста. Допустим, наш тест не прошёл. Полученный zip-файл можно просмотреть в инструменте просмотра трассировки на https://trace.playwright.dev/
На картинке ниже в верхней части страницы у нас временная шкала прохождения теста и скриншоты для каждого периода времени. Цветами выделены различные события, поэтому мы можем сразу перейти к определённому моменту в нашем тесте. Слева список выполненных шагов, можно щёлкнуть на шаг, чтобы перейти на соответствующее место на временной шкале.
В центре страницы находится наш скриншот. Но что важно, мы можем переключать вкладки для представления «До» (Before) и «После» (After). Это безумно удобно при вводе текста или при заполнении других полей ввода. Представьте, что тест пытается заполнить очень большую форму, и на самом первом шаге он неправильно заполняет текстовое поле. Тест потерпит неудачу только при отправке формы и проверке данных, но на скриншоте в моменте возникновения ошибки мы можем даже не увидеть само текстовое поле. Playwright даёт нам пошаговое представление о каждом шаге теста, происходящем по мере его прохождения.
Справа есть куча отладочной информации, включая отладочный вывод Playwright, консольный вывод браузера, сетевой вывод браузера (аналогично инструментам разработчика Chrome/Firefox), а также исходный код нашего текста с выделенным текущим шагом.
Это невероятно полезно. Если тест терпит неудачу, мы можем точно знать, где в нашем коде он был и что пытался сделать.
Источник: https://dotnetcoretutorials.com/2022/05/20/using-playwright-e2e-tests-with-c-net/
👍7
День 1284. #ЗаметкиНаПолях
Генерация Сортируемых Guid с Помощью NewId. Начало
NewId предназначен случаев, когда вам нужен уникальный идентификатор, но, по возможности, сортируемый и предсказуемый, например для первичных ключей в базах данных.
Большинство используют:
-
-
Рассмотрим плюсы и минусы каждого подхода.
1. Генерация в базе данных
Плюсы:
- Первичные ключи получают красивые, монотонно возрастающие (и обычно последовательные) идентификаторы.
- Упрощается работа с тестовыми данными. Идентификаторы часто появляются в URL-адресах, и простые последовательные идентификаторы очень удобно использовать.
Минусы:
- Невозможность использования некоторых паттернов проектирования. Например, распространённый подход к идемпотентности заключается в создании идентификатора на клиенте и отправке его в запросе. Это устраняет дублирование и гарантирует, что вы не вставите один и тот же объект дважды, так как легко обнаружить повторяющиеся запросы на вставку. Такой подход обычно невозможен с идентификаторами, сгенерированными базой данных.
- Усложнение кода вставки, чтобы возвращать сгенерированные идентификаторы. ORM, такие как EF Core, инкапсулируют эту логику, но, например, при использовании Dapper, вам придётся это делать самому.
- При вставке тысяч строк в секунду, «блокировка» базы данных вокруг генератора идентификаторов иногда может стать узким местом.
- Масштабирование «вширину» затруднено из-за необходимости координировать идентификаторы между всеми серверами.
2. Генерация GUID на клиенте
Плюсы:
- Лёгкость. Все современные языки имеют доступные генераторы UUID; в .NET это
- Лёгкий доступ к различным шаблонам идемпотентности. Если запрос на вставку завершается сбоем из-за ошибки сервера, можно безбоязненно отправить тот же запрос ещё раз, зная, что сервер сможет идентифицировать возможный дубликат (т.к. ключ тот же), и избежать создания повторяющихся сущностей.
Случайность Guid - это и их сила, и их слабость.
Минусы:
- Для разработчика, тестирующего код, с
- В базе данных эта случайность идентификаторов может привести к серьезной фрагментации индекса, что увеличивает размер вашей базы данных и влияет на общую производительность. Также UUID являются 128-битными по сравнению с 32-битными целыми числами, поэтому больше и чистый размер хранимых данных.
Окончание следует…
Источник: https://andrewlock.net/generating-sortable-guids-using-newid/
Генерация Сортируемых Guid с Помощью NewId. Начало
NewId предназначен случаев, когда вам нужен уникальный идентификатор, но, по возможности, сортируемый и предсказуемый, например для первичных ключей в базах данных.
Большинство используют:
-
int
и позволяют базе данных генерировать первичный ключ при вставке строки,-
Guid
, генерируя идентификатор в своём приложении и вставляя его в строку.Рассмотрим плюсы и минусы каждого подхода.
1. Генерация в базе данных
Плюсы:
- Первичные ключи получают красивые, монотонно возрастающие (и обычно последовательные) идентификаторы.
- Упрощается работа с тестовыми данными. Идентификаторы часто появляются в URL-адресах, и простые последовательные идентификаторы очень удобно использовать.
Минусы:
- Невозможность использования некоторых паттернов проектирования. Например, распространённый подход к идемпотентности заключается в создании идентификатора на клиенте и отправке его в запросе. Это устраняет дублирование и гарантирует, что вы не вставите один и тот же объект дважды, так как легко обнаружить повторяющиеся запросы на вставку. Такой подход обычно невозможен с идентификаторами, сгенерированными базой данных.
- Усложнение кода вставки, чтобы возвращать сгенерированные идентификаторы. ORM, такие как EF Core, инкапсулируют эту логику, но, например, при использовании Dapper, вам придётся это делать самому.
- При вставке тысяч строк в секунду, «блокировка» базы данных вокруг генератора идентификаторов иногда может стать узким местом.
- Масштабирование «вширину» затруднено из-за необходимости координировать идентификаторы между всеми серверами.
2. Генерация GUID на клиенте
Плюсы:
- Лёгкость. Все современные языки имеют доступные генераторы UUID; в .NET это
Guid.NewGuid()
, который возвращает случайный 128-битный идентификатор. Генерация его на клиенте и вставка позволяет не беспокоиться о том, что было сгенерировано в БД. В EF Core или Dapper, Postgres или SqlServer - всё одинаково. Данные перемещаются только в одном направлении: от клиента к базе данных.- Лёгкий доступ к различным шаблонам идемпотентности. Если запрос на вставку завершается сбоем из-за ошибки сервера, можно безбоязненно отправить тот же запрос ещё раз, зная, что сервер сможет идентифицировать возможный дубликат (т.к. ключ тот же), и избежать создания повторяющихся сущностей.
Случайность Guid - это и их сила, и их слабость.
Минусы:
- Для разработчика, тестирующего код, с
/my-entity/be170000-f22d-18db-02db-08da21702e9f
определённо не так просто работать, как с /my-entity/1
.- В базе данных эта случайность идентификаторов может привести к серьезной фрагментации индекса, что увеличивает размер вашей базы данных и влияет на общую производительность. Также UUID являются 128-битными по сравнению с 32-битными целыми числами, поэтому больше и чистый размер хранимых данных.
Окончание следует…
Источник: https://andrewlock.net/generating-sortable-guids-using-newid/
👍3
День 1285. #NuGet
Генерация Сортируемых Guid с Помощью NewId. Окончание
Начало
NewId вместо полностью случайных Guid предоставляет UUID, который можно легко отсортировать. Рассмотрим простое приложение:
-
-
-
NewId использует 3 разных источника для создания идентификатора:
1. ID машины/процесса – константа для данной машины (может быть настроена для включения идентификатора процесса).
2. Временную метку - обеспечивает базовый порядок идентификатора.
3. Последовательность - увеличивающийся идентификатор.
Объединив все 3 вместе, вы можете получить идентификатор, который (с натяжкой) упорядочен благодаря компоненту метки времени. Включив идентификатор рабочего процесса, вы можете заставить процессы генерировать независимые ID, избегая при этом коллизий. Это можно сделать, например, вызвав в начале программы:
Очевидно, что такие ID приводят к гораздо менее фрагментированному индексу базы данных. Конечно, с идеально последовательными целыми числами они не сравнятся. Но сравнение индексов в оригинальной статье показало, что полностью случайные Guid приводят к почти 99% фрагментации индекса, тогда как фрагментация индекса NewId составляет лишь 5%.
Сгенерированные идентификаторы предсказуемы по своей сути. Их не следует использовать в сценариях, где желательна непредсказуемость. Эти идентификаторы НЕ должны использоваться для:
- генерации паролей,
- токенов безопасности
- ничего другого, когда нежелательно угадывание значения.
Идентификаторы, сгенерированные NewId, раскрывают личность машины, сгенерировавшей идентификатор (фактически, это её MAC-адрес), и время, когда она это сделала. Это может быть проблемой для некоторых чувствительных к безопасности приложений.
Источник: https://andrewlock.net/generating-sortable-guids-using-newid/
Генерация Сортируемых Guid с Помощью NewId. Окончание
Начало
NewId вместо полностью случайных Guid предоставляет UUID, который можно легко отсортировать. Рассмотрим простое приложение:
using MassTransit;Эта программа генерирует 5 идентификаторов. В результате получается что-то вроде этого:
foreach (var i in Enumerable.Range(0, 5))
{
NewId id = NewId.Next();
Console.WriteLine(id);
}
be170000-f32d-18db-de59-08da26f2ad5aНа первый взгляд может показаться, что все они одинаковы, но давайте разобьём первый экземпляр на 3 части:
be170000-f32d-18db-1816-08da26f2ad5b
be170000-f32d-18db-8694-08da26f2ad5b
be170000-f32d-18db-4dbd-08da26f2ad5b
be170000-f32d-18db-65b3-08da26f2ad5c
-
be170000-f32d-18db
— очевидно, это постоянное значение для всех идентификаторов.-
de59
— меняется с каждым ID.-
08da26f2ad5a
— иногда меняется, и меняется постепенно.NewId использует 3 разных источника для создания идентификатора:
1. ID машины/процесса – константа для данной машины (может быть настроена для включения идентификатора процесса).
2. Временную метку - обеспечивает базовый порядок идентификатора.
3. Последовательность - увеличивающийся идентификатор.
Объединив все 3 вместе, вы можете получить идентификатор, который (с натяжкой) упорядочен благодаря компоненту метки времени. Включив идентификатор рабочего процесса, вы можете заставить процессы генерировать независимые ID, избегая при этом коллизий. Это можно сделать, например, вызвав в начале программы:
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());А использование «последовательности» означает, что вы можете генерировать 2^16-1 идентификаторов в миллисекунду для каждого процесса/машины.
Очевидно, что такие ID приводят к гораздо менее фрагментированному индексу базы данных. Конечно, с идеально последовательными целыми числами они не сравнятся. Но сравнение индексов в оригинальной статье показало, что полностью случайные Guid приводят к почти 99% фрагментации индекса, тогда как фрагментация индекса NewId составляет лишь 5%.
Сгенерированные идентификаторы предсказуемы по своей сути. Их не следует использовать в сценариях, где желательна непредсказуемость. Эти идентификаторы НЕ должны использоваться для:
- генерации паролей,
- токенов безопасности
- ничего другого, когда нежелательно угадывание значения.
Идентификаторы, сгенерированные NewId, раскрывают личность машины, сгенерировавшей идентификатор (фактически, это её MAC-адрес), и время, когда она это сделала. Это может быть проблемой для некоторых чувствительных к безопасности приложений.
Источник: https://andrewlock.net/generating-sortable-guids-using-newid/
👍16
День 1286. #ЗаметкиНаПолях #AsyncTips
Реагирование на Запросы на Отмену Посредством Периодического Опроса
Задача: В коде имеется цикл, который должен поддерживать отмену.
Решение
Если в коде присутствует цикл обработки, то в нём нет низкоуровневых функций API, которым можно было передать
В большинстве случаев ваш код должен просто передать
У типа
Работа метода
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
Реагирование на Запросы на Отмену Посредством Периодического Опроса
Задача: В коде имеется цикл, который должен поддерживать отмену.
Решение
Если в коде присутствует цикл обработки, то в нём нет низкоуровневых функций API, которым можно было передать
CancellationToken
. В этом случае необходимо периодически проверять, не был ли отменён токен. Следующий пример периодически проверяет токен в ходе выполнения цикла, создающего вычислительную нагрузку на процессор:public int Cancelable(CancellationToken ct)Если тело цикла выполняется очень быстро, то, возможно, стоит ограничить частоту проверки токена отмены. Измерьте быстродействие до и после таких изменений, чтобы выбрать лучший вариант. Следующий пример похож на предыдущий, но выполняет больше итераций более быстрого цикла, поэтому добавлено ограничение на частоту проверки маркера:
{
for (int i = 0; i != 100; ++i)
{
Thread.Sleep(1000); // вычисления
ct.ThrowIfCancellationRequested();
}
return 42;
}
public int Cancelable(CancellationToken ct)Оптимальная частота опроса зависит исключительно от того, какой объём работы выполняется и насколько быстрой должна быть реакция на отмену.
{
for (int i = 0; i != 100000; ++i)
{
Thread.Sleep(1); // вычисления
if (i % 1000 == 0)
ct.ThrowIfCancellationRequested();
}
return 42;
}
В большинстве случаев ваш код должен просто передать
CancellationToken
на следующий уровень. Метод периодического опроса (polling), использованный в этом рецепте, следует применять только в том случае, если у вас имеется вычислительный цикл, который должен поддерживать отмену.У типа
CancellationToken
имеется другой метод IsCancellationRequested
, который начинает возвращать true при отмене токена. Некоторые разработчики используют его для реакции на отмену, обычно возвращая значение по умолчанию или null. В большинстве случаев использовать этот метод не рекомендуется. В стандартном паттерне отмены выдаётся исключение OperationCanceledException
, для чего вызывается метод ThrowIfCancellationRequested
. Если код, находящийся выше в стеке, захочет перехватить исключение и действовать так, словно результат равен null, это нормально, но любой код, получающий CancellationToken
, должен следовать стандартному паттерну отмены. Если вы решите не соблюдать паттерн отмены, по крайней мере чётко документируйте свои намерения.Работа метода
ThrowIfCancellationRequested
основана на периодическом опросе токена отмены; ваш код должен вызывать его с регулярными интервалами. Также существует способ регистрации обратного вызова, который вызывается при запросе на отмену. Об этом в будущих постах.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
👍4
День 1287. #ЗаметкиНаПолях
Рекомендации по Обеспечению Безопасности Проектов на GitHub
Сегодня ПО подвержено постоянно меняющемуся набору угроз. Вот как вы можете защитить свои проекты на GitHub.
Средний проект на GitHub напрямую использует около 10 зависимостей с открытым исходным кодом. Это, наверное, неудивительно, но удивительно, что тот же репозиторий использует более 600 транзитивных зависимостей, которые получаются из 10 прямых зависимостей.
Огромное количество зависимостей, которые использует большинство проектов, означает, что если вы не используете автоматизацию для постоянного отслеживания уязвимостей и обновления, то, скорее всего, ваш проект уже уязвим. Хотя большинство уязвимостей в системе безопасности не являются злонамеренными, они возникают из-за случайных ошибок в коде, но они все же могут открыть дверь для злоумышленников, которые могут преследовать ваших пользователей или их данные.
GitHub предоставляет ряд встроенных инструментов, предназначенных для помощи в управлении деревом зависимостей, включая граф зависимостей и проверку зависимостей.
1. Для каждого репозитория граф зависимостей показывает зависимости, экосистемы и пакеты, на которых основана каждая зависимость. Граф зависимостей можно посмотреть на вкладке Insights вашего репозитория.
Подробнее про граф зависимостей.
2. Проверка зависимостей позволяет вам быстро просмотреть ваши зависимости. В рамках пул реквеста вы можете увидеть, что вы вводите, изменяете или удаляете, а также информацию об уязвимостях, лицензии и правилах использования. Проверка зависимостей даст вам:
- Информацию об уязвимостях в этой версии зависимости, а также её серьёзность и наличие более новой, исправленной версии.
- Информацию о лицензии для каждой зависимости.
Подробнее про проверку зависимостей.
3. При помощи Dependabot вы можете не только обнаруживать уязвимые зависимости, но и исправлять их. Он автоматически проверяет ваши файлы зависимостей на наличие устаревших зависимостей и открывает для каждой отдельный пул реквест. Затем он уведомляет вас и предлагает исправления, позволяя вам всегда работать с последними и наиболее безопасными выпусками.
Оповещения Dependabot можно включить как в общедоступных, так и в частных репозиториях. Вы также можете настроить уведомления, чтобы получать только те уведомления, которые вам нужны, и ничего больше. Кроме того, вы можете увидеть все оповещения, которые влияют на конкретный проект, на вкладке безопасности или в графе зависимостей.
Чтобы включить Dependabot, на главной странице репозитория под именем репозитория нажмите на вкладку Settings (Настройки). В левой боковой панели нажмите на Code security and analysis (Безопасность и анализ кода). На этой странице включите Dependency graph (Граф зависимостей), (Dependabot alerts) Предупреждения Dependabot и Dependabot security updates (Обновления безопасности Dependabot).
После этого GitHub предложит вам добавить файл dependabot.yml в папку
Источник: https://github.blog/2022-04-28-best-practices-to-keep-your-projects-secure-on-github/
Рекомендации по Обеспечению Безопасности Проектов на GitHub
Сегодня ПО подвержено постоянно меняющемуся набору угроз. Вот как вы можете защитить свои проекты на GitHub.
Средний проект на GitHub напрямую использует около 10 зависимостей с открытым исходным кодом. Это, наверное, неудивительно, но удивительно, что тот же репозиторий использует более 600 транзитивных зависимостей, которые получаются из 10 прямых зависимостей.
Огромное количество зависимостей, которые использует большинство проектов, означает, что если вы не используете автоматизацию для постоянного отслеживания уязвимостей и обновления, то, скорее всего, ваш проект уже уязвим. Хотя большинство уязвимостей в системе безопасности не являются злонамеренными, они возникают из-за случайных ошибок в коде, но они все же могут открыть дверь для злоумышленников, которые могут преследовать ваших пользователей или их данные.
GitHub предоставляет ряд встроенных инструментов, предназначенных для помощи в управлении деревом зависимостей, включая граф зависимостей и проверку зависимостей.
1. Для каждого репозитория граф зависимостей показывает зависимости, экосистемы и пакеты, на которых основана каждая зависимость. Граф зависимостей можно посмотреть на вкладке Insights вашего репозитория.
Подробнее про граф зависимостей.
2. Проверка зависимостей позволяет вам быстро просмотреть ваши зависимости. В рамках пул реквеста вы можете увидеть, что вы вводите, изменяете или удаляете, а также информацию об уязвимостях, лицензии и правилах использования. Проверка зависимостей даст вам:
- Информацию об уязвимостях в этой версии зависимости, а также её серьёзность и наличие более новой, исправленной версии.
- Информацию о лицензии для каждой зависимости.
Подробнее про проверку зависимостей.
3. При помощи Dependabot вы можете не только обнаруживать уязвимые зависимости, но и исправлять их. Он автоматически проверяет ваши файлы зависимостей на наличие устаревших зависимостей и открывает для каждой отдельный пул реквест. Затем он уведомляет вас и предлагает исправления, позволяя вам всегда работать с последними и наиболее безопасными выпусками.
Оповещения Dependabot можно включить как в общедоступных, так и в частных репозиториях. Вы также можете настроить уведомления, чтобы получать только те уведомления, которые вам нужны, и ничего больше. Кроме того, вы можете увидеть все оповещения, которые влияют на конкретный проект, на вкладке безопасности или в графе зависимостей.
Чтобы включить Dependabot, на главной странице репозитория под именем репозитория нажмите на вкладку Settings (Настройки). В левой боковой панели нажмите на Code security and analysis (Безопасность и анализ кода). На этой странице включите Dependency graph (Граф зависимостей), (Dependabot alerts) Предупреждения Dependabot и Dependabot security updates (Обновления безопасности Dependabot).
После этого GitHub предложит вам добавить файл dependabot.yml в папку
.github
вашего репозитория. В этом файле вам нужно будет настроить параметр package-ecosystem
- "nuget"
для проектов на .NET и schedule
> interval
– для желаемой частоты проверок.Источник: https://github.blog/2022-04-28-best-practices-to-keep-your-projects-secure-on-github/
👍5
DotNext возвращается!
В ноябре JUG Ru Group организует конференцию для .NET‑разработчиков — DotNext 2022 Autumn. В программе — технические доклады и дискуссии об архитектуре, производительности, безопасности, фреймворках и инструментах.
Участники конференции любят обсуждать нетривиальные задачи и новые подходы в .NET‑разработке. И если вам есть что сказать, тогда подавайте заявку на выступление: https://bit.ly/3zDv3Zk
Программный комитет поможет с подготовкой к выступлению: назначит персонального куратора, проведет ревью материала и организует репетиции.
Выбирайте тему выступления на сайте или предлагайте свои идеи — их обязательно рассмотрят.
Всем спикерам JUG Ru Group дарит билет на все конференции сезона в онлайне и офлайне.
А билеты можно купить здесь: https://bit.ly/3Qdd5np
В ноябре JUG Ru Group организует конференцию для .NET‑разработчиков — DotNext 2022 Autumn. В программе — технические доклады и дискуссии об архитектуре, производительности, безопасности, фреймворках и инструментах.
Участники конференции любят обсуждать нетривиальные задачи и новые подходы в .NET‑разработке. И если вам есть что сказать, тогда подавайте заявку на выступление: https://bit.ly/3zDv3Zk
Программный комитет поможет с подготовкой к выступлению: назначит персонального куратора, проведет ревью материала и организует репетиции.
Выбирайте тему выступления на сайте или предлагайте свои идеи — их обязательно рассмотрят.
Всем спикерам JUG Ru Group дарит билет на все конференции сезона в онлайне и офлайне.
А билеты можно купить здесь: https://bit.ly/3Qdd5np
👍5
День 1288. #TypesAndLanguages
6. Запрещать или Разрешать при Разработке ПО
Дискуссии в области разработки ПО довольно часто касаются личных предпочтений. Несмотря на то, что все участники дебатов спорят, основываясь на своих знаниях, навыках или опыте, их дискуссии довольно часто сводятся к вопросу вкуса и цвета.
Одним из примеров является спор «Открытое Наследование или Разрешённое Наследование» Мартина Фаулера. Вопрос в том, должны ли мы по умолчанию разрешать наследование класса или блокировать его. Мы можем привести множество аргументов за и против, но нет единого показателя, показывающего, какой подход лучше. То же самое относится к тому, чтобы сделать методы виртуальными или запечатанными по умолчанию. Или о том, насколько всё делать приватным или открытым. Эти дискуссии, как правило, основаны на личном ощущении участников дебатов, и может быть довольно занимательно узнавать аргументацию, стоящую за каждым из вариантов.
Возьмем отрешённый пример. Представьте, что вы возвращаетесь домой ночью, в темном переулке, и тут появляются какие-то люди, бьют вас, забирают телефон и исчезают. Как правило, после такой ситуации вы можете использовать три разных подхода:
1. Вы решаете избегать таких встреч, насколько это возможно. Вы не возвращаетесь домой ночью, избегаете темных переулков или даже остаётесь дома. По сути, вы заставляете себя избегать проблемы.
2. Вы утверждаете, что такой ситуации быть не должно, что полиция должна быть ночью на улице, чтобы помочь вам в таком случае. Вы заставляете других сделать так, чтобы такая ситуация больше не повторилась.
3. Вы также можете пойти в спортзал, научиться боксу или боевым искусствам или носить оружие, чтобы в следующий раз быть готовым и не дать им забрать ваш телефон. По сути, вы заставляете себя принять ситуацию.
Вам решать, какой вариант вы выберете. Хотя вы можете возразить, что некоторые из них невыполнимы в вашем случае или нежелательны.
То же самое относится и к разработке ПО. Допустим, вы нашли ошибку в длинной функции, меняющей состояние приложения. Что вы сделаете? Варианты:
1. Вы решаете, что вы и ваша команда больше не будете так писать. Вы делаете акцент на обзорах кода, чтобы не пропускать такие функции.
2. Вы решаете, что такие функции вообще нельзя разрешать. Вы меняете свой стек на использование чистых функций (например, на F# или Haskell).
3. Вы просто улучшаете свои навыки, чтобы лучше поддерживать длинные функции, меняющие состояние приложения.
Похоже, что индустрия обычно выбирает первый вариант. В сети можно много прочитать о «чистом коде». Такие принципы, как «метод должен иметь не более двух параметров», подкрепляются такими утверждениями, как «Я работаю в отрасли уже 30 лет, поэтому я знаю лучше». Однако в итоге это просто вопрос личных предпочтений. На предпочтение могут влиять когнитивные навыки, окружающая среда, опыт, мастерство, риск, стоимость и, возможно, многие другие причины. Однако нет метрик, показывающих, что «контейнеры DI — это плохо» (как говорят Java-программисты, в то время как .NET-программисты получают поддержку DI «из коробки» в .NET Core), «функции должны иметь длину не более 10 строк» (а затем вы видите, что пул реквесты в коде ядра Linux делают совершенно по-другому), или «чистые функции лучше, чем нечистые» (а затем вы заворачиваете свой код в морской узел, чтобы создать конечный автомат без состояния в нём).
Должны ли мы запрещать или разрешать? Я склоняюсь к последнему. Но опять же, это вопрос предпочтений.
Источник: https://blog.adamfurmanek.pl/2022/07/16/types-and-programming-languages-part-15/
6. Запрещать или Разрешать при Разработке ПО
Дискуссии в области разработки ПО довольно часто касаются личных предпочтений. Несмотря на то, что все участники дебатов спорят, основываясь на своих знаниях, навыках или опыте, их дискуссии довольно часто сводятся к вопросу вкуса и цвета.
Одним из примеров является спор «Открытое Наследование или Разрешённое Наследование» Мартина Фаулера. Вопрос в том, должны ли мы по умолчанию разрешать наследование класса или блокировать его. Мы можем привести множество аргументов за и против, но нет единого показателя, показывающего, какой подход лучше. То же самое относится к тому, чтобы сделать методы виртуальными или запечатанными по умолчанию. Или о том, насколько всё делать приватным или открытым. Эти дискуссии, как правило, основаны на личном ощущении участников дебатов, и может быть довольно занимательно узнавать аргументацию, стоящую за каждым из вариантов.
Возьмем отрешённый пример. Представьте, что вы возвращаетесь домой ночью, в темном переулке, и тут появляются какие-то люди, бьют вас, забирают телефон и исчезают. Как правило, после такой ситуации вы можете использовать три разных подхода:
1. Вы решаете избегать таких встреч, насколько это возможно. Вы не возвращаетесь домой ночью, избегаете темных переулков или даже остаётесь дома. По сути, вы заставляете себя избегать проблемы.
2. Вы утверждаете, что такой ситуации быть не должно, что полиция должна быть ночью на улице, чтобы помочь вам в таком случае. Вы заставляете других сделать так, чтобы такая ситуация больше не повторилась.
3. Вы также можете пойти в спортзал, научиться боксу или боевым искусствам или носить оружие, чтобы в следующий раз быть готовым и не дать им забрать ваш телефон. По сути, вы заставляете себя принять ситуацию.
Вам решать, какой вариант вы выберете. Хотя вы можете возразить, что некоторые из них невыполнимы в вашем случае или нежелательны.
То же самое относится и к разработке ПО. Допустим, вы нашли ошибку в длинной функции, меняющей состояние приложения. Что вы сделаете? Варианты:
1. Вы решаете, что вы и ваша команда больше не будете так писать. Вы делаете акцент на обзорах кода, чтобы не пропускать такие функции.
2. Вы решаете, что такие функции вообще нельзя разрешать. Вы меняете свой стек на использование чистых функций (например, на F# или Haskell).
3. Вы просто улучшаете свои навыки, чтобы лучше поддерживать длинные функции, меняющие состояние приложения.
Похоже, что индустрия обычно выбирает первый вариант. В сети можно много прочитать о «чистом коде». Такие принципы, как «метод должен иметь не более двух параметров», подкрепляются такими утверждениями, как «Я работаю в отрасли уже 30 лет, поэтому я знаю лучше». Однако в итоге это просто вопрос личных предпочтений. На предпочтение могут влиять когнитивные навыки, окружающая среда, опыт, мастерство, риск, стоимость и, возможно, многие другие причины. Однако нет метрик, показывающих, что «контейнеры DI — это плохо» (как говорят Java-программисты, в то время как .NET-программисты получают поддержку DI «из коробки» в .NET Core), «функции должны иметь длину не более 10 строк» (а затем вы видите, что пул реквесты в коде ядра Linux делают совершенно по-другому), или «чистые функции лучше, чем нечистые» (а затем вы заворачиваете свой код в морской узел, чтобы создать конечный автомат без состояния в нём).
Должны ли мы запрещать или разрешать? Я склоняюсь к последнему. Но опять же, это вопрос предпочтений.
Источник: https://blog.adamfurmanek.pl/2022/07/16/types-and-programming-languages-part-15/
👍10
День 1289. #ЗаметкиНаПолях
Хранение Динамических Данных с Помощью EF Core. Начало
Рассмотрим, как можно хранить «динамические» пользовательские данные с помощью Entity Framework Core. Динамические в том смысле, что вы можете не знать, какими будут пары данных ключ/значение, но их по-прежнему важно сохранить. На ум приходят два способа, каждый со своими преимуществами и недостатками. Сегодня рассмотрим первый.
1. Использование сериализации/десериализации JSON
В Entity Framework Core вы можете использовать методы преобразования для сериализации данных при записи в базу данных и десериализации данных при чтении из таблицы.
Преимущества такого подхода:
- меньшая сложность в разработке схемы базы данных (просто ещё один столбец),
- быстрые чтение и запись.
Недостатки:
- сериализация/десериализация может быть дорогостоящей,
- вы либо получаете все пользовательские значения, либо ничего (нельзя выбрать, какие значения возвращаются в запросе).
Настройка
Во-первых, определим объект для хранения:
Следующий шаг — настроить преобразование как часть конфигурации EF Core. Здесь используется SQLite, но это должно работать с любой реляционной базой данных, которая может хранить текст в столбце.
Источник: https://khalidabuhakmeh.com/storing-dynamic-user-data-with-ef-core
Хранение Динамических Данных с Помощью EF Core. Начало
Рассмотрим, как можно хранить «динамические» пользовательские данные с помощью Entity Framework Core. Динамические в том смысле, что вы можете не знать, какими будут пары данных ключ/значение, но их по-прежнему важно сохранить. На ум приходят два способа, каждый со своими преимуществами и недостатками. Сегодня рассмотрим первый.
1. Использование сериализации/десериализации JSON
В Entity Framework Core вы можете использовать методы преобразования для сериализации данных при записи в базу данных и десериализации данных при чтении из таблицы.
Преимущества такого подхода:
- меньшая сложность в разработке схемы базы данных (просто ещё один столбец),
- быстрые чтение и запись.
Недостатки:
- сериализация/десериализация может быть дорогостоящей,
- вы либо получаете все пользовательские значения, либо ничего (нельзя выбрать, какие значения возвращаются в запросе).
Настройка
Во-первых, определим объект для хранения:
public class Entity
{
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
= DateTime.UtcNow;
public Dictionary<string, string>
Values { get; set; } = new();
}
Dictionary<string,string>
выбран ради простоты использования с System.Text.Json, в котором нет конвертера для Dictionary<string,object>
. Хотя конвертер можно написать, как это сделал Йозеф Оттоссон в своем блоге.Следующий шаг — настроить преобразование как часть конфигурации EF Core. Здесь используется SQLite, но это должно работать с любой реляционной базой данных, которая может хранить текст в столбце.
public class Database : DbContextДля использования в коде, как и в любом словаре, нам нужно только предоставить словарю пару ключ/значение:
{
public DbSet<Entity> Entity { get; set; }
protected override void
OnModelCreating(ModelBuilder mb)
{
var opts = new JsonSerializerOptions(
JsonSerializerDefaults.General);
mb.Entity<Entity>()
.Property(x => x.Values)
.HasColumnName("Values")
.HasColumnType("BLOB")
.HasConversion(
v => JsonSerializer.Serialize(v, options),
s => JsonSerializer
.Deserialize<Dictionary<string, string>>(s, options),
ValueComparer.CreateDefault(
typeof(Dictionary<string, string>), true)
);
}
}
var json = new EntityОкончание следует…
{
Values = new()
{
{"Name", "Dotnet"},
{"Status", "Awesome"}
}
};
Источник: https://khalidabuhakmeh.com/storing-dynamic-user-data-with-ef-core
👍7
День 1290. #ЗаметкиНаПолях
Хранение Динамических Данных с Помощью EF Core. Окончание
Начало
2. Хранение пользовательских данных в инвертированной таблице
Инвертированные таблицы — это когда мы храним пары ключ/значение в отдельных строках. В этом случае ключи и значения становятся столбцами, что обеспечивает гибкость.
Преимущества такого подхода:
- Мы можем хранить «бесконечное» количество пользовательских данных.
- Мы можем отфильтровать отдельные строки, чтобы получить одно значение.
- Мы можем реализовать логику уникальности ключей для каждой сущности.
Недостатки:
- Столбцы значений должны иметь строгий тип, скорее всего строковый тип.
- Эти таблицы могут быстро расти в зависимости от объема пользовательских данных.
Настройка
Настройка инвертированной таблицы не отличается от типичных отношений «один ко многим».
Посмотрим, как сохранить эти пользовательские значения:
Хранение Динамических Данных с Помощью EF Core. Окончание
Начало
2. Хранение пользовательских данных в инвертированной таблице
Инвертированные таблицы — это когда мы храним пары ключ/значение в отдельных строках. В этом случае ключи и значения становятся столбцами, что обеспечивает гибкость.
Преимущества такого подхода:
- Мы можем хранить «бесконечное» количество пользовательских данных.
- Мы можем отфильтровать отдельные строки, чтобы получить одно значение.
- Мы можем реализовать логику уникальности ключей для каждой сущности.
Недостатки:
- Столбцы значений должны иметь строгий тип, скорее всего строковый тип.
- Эти таблицы могут быстро расти в зависимости от объема пользовательских данных.
Настройка
Настройка инвертированной таблицы не отличается от типичных отношений «один ко многим».
public class EntityМетод
{
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
= DateTime.UtcNow;
public ICollection<Values> Values { get; set; }
= new List<Values>();
public Entity AddValue(string name, string value)
{
var existing = Values?.
FirstOrDefault(v => v.Name.Equals(name));
if (existing is { })
existing.Value = value;
else
Values?.Add(
new Values {Name = name, Value = value}
);
return this;
}
}
public class Values
{
public int Id { get; set; }
public int EntityId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
AddValue
в типе Entity
будет работать с оговоркой, что у вас есть все значения из связанной таблицы Values
в памяти. Если нет, вы получите повторяющиеся пары ключ/значение в своей коллекции.Посмотрим, как сохранить эти пользовательские значения:
var invertedTable = new Entity()Разница с первым методом в том, что подход с инвертированной таблицей требует включения значений при чтении сущностей из базы данных:
.AddValue("Name", "Dotnet")
.AddValue("Status", "Awesome");
var invertedTable = dbВызов
.EntityWithInvertedTables
.OrderByDescending(o => o.CreatedAt)
.Include(x => x.Values)
.First();
Include
загрузит все значения из связанной таблицы. Хотя, вы можете загрузить только нужные значения (но помните, что в этом случае метод сущности AddValue
перестанет корректно работать):…Источник: https://khalidabuhakmeh.com/storing-dynamic-user-data-with-ef-core
.Include(x => x.Values.Where(v => v.Name == "Name"))
.First();
👍3