На самом деле тут можно представить немного иначе 1 уровень: Абстракция над железом (языки программирования) 2 уровень: Абстрация над над реализацией(протоколы JSON, SQL, XML…) но не столько как сами эти технологии, сколько апи построенное на их базе 3 уровень: по идее это должна быть абстракция над интерфейсом, я не считаю что ИИ как то решает эту проблему, я скорее воспринимаю ИИ как инструмент, например как IDE. А вот тот же neuralink и вполне возможно
На самом деле тут зависит от того какую пагинацию вы реализуете, если у вас в сервисе именно фиксированные страницы, то да, но тут есть проблема, если данные в процессе добавляются в начало, то все данные съезжают, то есть на новой странице вы можете увидеть данные, которые уже видели на предыдущей. Другой подход last_id/limit, то есть вы получаете данные не с конкретного offset, а с конкретного id, это позволяет делать пагинацию как единую ленту
Я в pet проектах делаю гибридные решения, мне не нравится использовать методы http, раз сервис SPA использую только POST хотя url обычные, не endpoint в теле, так лучше видно запросы в браузере при отладке на вкладке network, GET остаётся для фронта, в GET есть кеширование, но как его инвалидировать? Проще сделать кеширование на уровне сервиса, так есть полный контроль для кеша.
Кстати, ваш баг связан с другим, по логике у вас наоборот должен обновляться если даже значения не поменялись, тут уже проблема ef, что он не сравнивает json поля, на это тоже натыкался
UPD: Хмм а если вы не изменили ссылку, а в том же массиве или коллекции поменяли значения, то да, ef не обновит значения
Точно, я почему-то думал, что Equals в record проверяет есть ли у объекта IStructuralEqutable и если есть использует его, оказывается нет, забавно, хотя справедливости ради редко сравниваю record и не использую ключи для Dictionary где есть поля массивы
Но кстати, для ef тут еще зависит от провайдера, например просто массивы в pg, ef сравнивает через IStructuralEqutable
Потому что когда record только появились некоторые фишки заехали вместе с ними, и были применимы только к ним
например, сейчас я могу писать
public record Address(string City, string Street);
public class Address(string City, string Street);
public record Address
{
public string City { get; set; }
public string Street { get; set; }
}
public class Address
{
public string City { get; set; }
public string Street { get; set; }
}
Вообще фишка с “иммутабельный по-умолчанию” это про случай где есть только primary констуктор и все
public record Address(string City, string Street);
Поэтому правильный ответ тут в том, что record от класса тем, что у него переопределены методы ToString(), GetHashCode(), Equals()
А в чём проблема? Нормально же работает, если стандартные коллекции, но тут конечно не без ньюансов, например если в dto вы используете коллекцию где dto тоже record, то это работает нормально, но если используете в dto коллекцию из объектов не примитавов и не record, то не понятно зачем вы это делаете и что хотите получить
Я вообще не понимаю зачем генерировать класс менеджер, если менеджер это по сути роль в команде, любой сотрудник может стать менеджером в какой то момент, и не просто менеджером, а менеджером какого-то подразделения, но тут уже у самого подразделения просто должно быть поле менеджер, и кто там проставлен тот и менеджер. А то как вы реализуете ИО Менеджер и тому подобные вещи
Я для себя использую гибрид так как обычно пишу бэк для Single Page Application У меня все запросы POST (кроме аутентификации, там GET по стандарту) Ошибки делятся на инфраструктурные и ошибки бизнес логики (инфраструктурные - это те которые можно описать на уровне middleware для всех запросов например 401, 403) такие ошибки обрабатываются на фронте так же на уровне всего приложения В отличии от JsonRpc статус success или error пишу в хедере, чтобы тело запроса можно было сразу десериллизовать в нужный тип, traceId так же в хедере, нет params так как не требуются batch запросы, зато можно результат возвращать стримом по мере поступления данных и сваггер выглядит нормально, да и в Google Chrome Developer путь запроса нормально отображается и не приходится гадать, а какой там метод вызывался с фронта
Это не так, тут почти всё как в вашем примере, IAction - это ваш IBusinesOperation, просто букв меньше, и он параметризирован, чтобы можно было указать входные и выходные параметры, а не просто void и без входных параметров, из контейнера мы получаем sp.GetRequiredService<GetUserAction>() а не sp.GetRequiredService<IAction<Guid, UserDto>>()
Нас не интересует получение по IAction<,>, он только как интерфейс маркер для того чтобы получить все классы которые его реализуют, чтобы можно было их зарегистрировать, ну и чтобы название метода строго задать, чтобы всё вразнабой не было
Работаем с Actions так
public record GetUserRequest(Guid Id);
public class GetUserEndpoint(GetUserAction getUserAction): IEndpoint<GetUserRequest, UserDto>
{
public Task<UserDto> Handle(GetUserRequest request, CancellationToken cancellationToken)
=> getUserAction.Execute(request.Id, cancellationToken);
}
Идея хорошая, мы тоже к такой пришли, но вот реализация как тут совсем не гибкая, нет особого смысла разделять Command и Query, к этому даже в MediatR пришли, не хотите ничего возвращать, верните Unit
public interface IAction<in TRequest, TResponse>
{
Task<TResponse> Execute(TRequest request, CancellationToken cancellationToken)
}
public class GetUserAction(AppDbContext dbContext, IMapper mapper): IAction<Guid, UserDto>
{
public virtual Task<UserDto> Execute(Guid request, CancellationToken cancellationToken)
{
return dbContext.Users
.Where(u => u.Id == request)
.ProjectTo<UserDto>(mapper.ConfigurationProvider)
.FirstOrDefaultAsync(cancellationToken) ?? throw new NotFoundException("User not found")
}
}
Нет смысла инжектить его потом по интерфейсу, для тестов метод можно сделать virtual тогда бизнес логику можно мокать
Так же мы у себя ввели правило, что мы не вызываем dbContext.SaveChangesAsync() в Action, только на уровне эндпоинта
По сути это похоже на медиатор, но медиатор - это сервис локатор, нам нужно погрузиться в бизнес логику, чтобы понять какие хендлеры он вызывает, тут же мы инжектим Action по имени класса, поэтому мы понимаем какие Action будут вызваны внутри и их можно замокать в тестах
Она была в начале, но потом было подписано соглашение о неразмещении вооружения на орбите. Собственно реклама о том что они собираются размещать вооружение может привести в к тому, что их объекты будут уничтожать сразу после вывода на орбиту. Поэтому этим никто и не занимается
Вроде виден намёк на размещение вооружения на орбите, но по идее это запрещено. Если нарушить этот запрет то ни о каком росте обороноспособности США нельзя будет говорить, так как вооружение появится на орбите и у других стран
Мне кажется такой синтаксис был бы удобнее
На самом деле тут можно представить немного иначе 1 уровень: Абстракция над железом (языки программирования) 2 уровень: Абстрация над над реализацией(протоколы JSON, SQL, XML…) но не столько как сами эти технологии, сколько апи построенное на их базе 3 уровень: по идее это должна быть абстракция над интерфейсом, я не считаю что ИИ как то решает эту проблему, я скорее воспринимаю ИИ как инструмент, например как IDE. А вот тот же neuralink и вполне возможно
На самом деле тут зависит от того какую пагинацию вы реализуете, если у вас в сервисе именно фиксированные страницы, то да, но тут есть проблема, если данные в процессе добавляются в начало, то все данные съезжают, то есть на новой странице вы можете увидеть данные, которые уже видели на предыдущей. Другой подход last_id/limit, то есть вы получаете данные не с конкретного offset, а с конкретного id, это позволяет делать пагинацию как единую ленту
Я в pet проектах делаю гибридные решения, мне не нравится использовать методы http, раз сервис SPA использую только POST хотя url обычные, не endpoint в теле, так лучше видно запросы в браузере при отладке на вкладке network, GET остаётся для фронта, в GET есть кеширование, но как его инвалидировать? Проще сделать кеширование на уровне сервиса, так есть полный контроль для кеша.
Можете посмотреть наколько вы близки к правде https://github.com/dotnet/roslyn/blob/6a8ea0e2e9c1bc4f1f1fd386383bb67fa9c8643e/src/Compilers/CSharp/Portable/Syntax/RecordDeclarationSyntax.cs#L11
Мы чуть проще поступали, в месте где меняем json через так же проставляем Entry.Property.IsModified = true
Кстати, ваш баг связан с другим, по логике у вас наоборот должен обновляться если даже значения не поменялись, тут уже проблема ef, что он не сравнивает json поля, на это тоже натыкался
UPD: Хмм а если вы не изменили ссылку, а в том же массиве или коллекции поменяли значения, то да, ef не обновит значения
Точно, я почему-то думал, что Equals в record проверяет есть ли у объекта IStructuralEqutable и если есть использует его, оказывается нет, забавно, хотя справедливости ради редко сравниваю record и не использую ключи для Dictionary где есть поля массивы
Но кстати, для ef тут еще зависит от провайдера, например просто массивы в pg, ef сравнивает через IStructuralEqutable
Потому что когда record только появились некоторые фишки заехали вместе с ними, и были применимы только к ним
например, сейчас я могу писать
Вообще фишка с “иммутабельный по-умолчанию” это про случай где есть только primary констуктор и все
Поэтому правильный ответ тут в том, что record от класса тем, что у него переопределены методы ToString(), GetHashCode(), Equals()
А в чём проблема? Нормально же работает, если стандартные коллекции, но тут конечно не без ньюансов, например если в dto вы используете коллекцию где dto тоже record, то это работает нормально, но если используете в dto коллекцию из объектов не примитавов и не record, то не понятно зачем вы это делаете и что хотите получить
Я вообще не понимаю зачем генерировать класс менеджер, если менеджер это по сути роль в команде, любой сотрудник может стать менеджером в какой то момент, и не просто менеджером, а менеджером какого-то подразделения, но тут уже у самого подразделения просто должно быть поле менеджер, и кто там проставлен тот и менеджер. А то как вы реализуете ИО Менеджер и тому подобные вещи
Я поэтому брал материнки от Gigabyte с dual bios
Я для себя использую гибрид так как обычно пишу бэк для Single Page Application
У меня все запросы POST (кроме аутентификации, там GET по стандарту)
Ошибки делятся на инфраструктурные и ошибки бизнес логики (инфраструктурные - это те которые можно описать на уровне middleware для всех запросов например 401, 403) такие ошибки обрабатываются на фронте так же на уровне всего приложения
В отличии от JsonRpc статус success или error пишу в хедере, чтобы тело запроса можно было сразу десериллизовать в нужный тип, traceId так же в хедере, нет params так как не требуются batch запросы, зато можно результат возвращать стримом по мере поступления данных и сваггер выглядит нормально, да и в Google Chrome Developer путь запроса нормально отображается и не приходится гадать, а какой там метод вызывался с фронта
у США и России есть противоспутниковое вооружение
Это не так, тут почти всё как в вашем примере, IAction - это ваш IBusinesOperation, просто букв меньше, и он параметризирован, чтобы можно было указать входные и выходные параметры, а не просто void и без входных параметров, из контейнера мы получаем
sp.GetRequiredService<GetUserAction>()а неsp.GetRequiredService<IAction<Guid, UserDto>>()По классу регистрация
Нас не интересует получение по
IAction<,>, он только как интерфейс маркер для того чтобы получить все классы которые его реализуют, чтобы можно было их зарегистрировать, ну и чтобы название метода строго задать, чтобы всё вразнабой не былоРаботаем с Actions так
Выглядит отвратительно же, как это читать вообще, вместо нормальной всем понятной логики сплошной бойлерплейт
Идея хорошая, мы тоже к такой пришли, но вот реализация как тут совсем не гибкая, нет особого смысла разделять Command и Query, к этому даже в MediatR пришли, не хотите ничего возвращать, верните Unit
Нет смысла инжектить его потом по интерфейсу, для тестов метод можно сделать virtual тогда бизнес логику можно мокать
Так же мы у себя ввели правило, что мы не вызываем dbContext.SaveChangesAsync() в Action, только на уровне эндпоинта
По сути это похоже на медиатор, но медиатор - это сервис локатор, нам нужно погрузиться в бизнес логику, чтобы понять какие хендлеры он вызывает, тут же мы инжектим Action по имени класса, поэтому мы понимаем какие Action будут вызваны внутри и их можно замокать в тестах
Она была в начале, но потом было подписано соглашение о неразмещении вооружения на орбите. Собственно реклама о том что они собираются размещать вооружение может привести в к тому, что их объекты будут уничтожать сразу после вывода на орбиту. Поэтому этим никто и не занимается
Вроде виден намёк на размещение вооружения на орбите, но по идее это запрещено. Если нарушить этот запрет то ни о каком росте обороноспособности США нельзя будет говорить, так как вооружение появится на орбите и у других стран