Непонятки с EF
this нужен лишь в проперти или в конструкторе. Один раз на весь класс. В остальных 10-20 случаях я лучше не буду тянуться до _, тем более, что чтобы в неё попасть, нужно постоянно в неё целиться. Даже если владеешь слепой печатью на английском - всё равно неудобно.
void DeleteUserById(int id)
{
using (var context = new MyDbContext())context.Users.Remove(x => x.Id == id);
context.SaveChanges();
}
А почему SaveChanges не вызывается автоматически при выходе за пределы контекста MyDbContext? Заставляют писать лишнюю, но очевидную строчку кода.
using (var context = new MyDbContext())
using (MyDbContext context = new())
Второй вариант лучше. В первом варианте var не несёт никакого смысла и просто семантический мусор. Я бы на месте создателей Шарпа позволил бы в таких конструкциях вообще не писать ничего перед context.
public class MyRepository { private readonly MyDbContext _dbContext; public MyRepository(MyDbContext dbContext) { _dbContext = dbContext; }
void DeleteUserById(int id)
{
using (var context = new MyDbContext())
context.Users.Remove(x => x.Id == id);
context.SaveChanges();
}
Когда я пишу свою репу, т.к. у меня нет БД и всё в файлах - это понятно, зачем мне своя репа. Когда вы тупо переписываете все функции EF, а потом ещё и юнит-тестируете их, вы просто душнилы. ))
Ну например потому что ты из контекста мог только выбирать данные (select).
Не в этом суть. То, что в контексте лишь выборка идёт, сам контекст прекрасно знает. Почему бы ему внутри себя не вызывать автоматом сохранение изменений при выходе за пределы контекста, если там кроме выборки ещё что-то изменилось? Ведь подавляющая часть сценариев - создали контекст, что-то сделали, сохранили изменения, вышли за предел. И все эти рутинные обязательные вызовы можно делать внутри себя.
Вот почему-то от ручного вызова Dispose каждый раз они нас избавили, от сохранения контекста - нет. Короче, там ещё улучшать и улучшать. Сишарп страдает от того, что слишком быстро идёт вперёд, но старьё не чистит. В результате в языке много мусора, в том числе синтаксического. По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость. Эта совместимость по большому счёту не нужна. Например, на моём проекте хоть и новый код и новые проекты в солюшене пишутся на новых версиях дотнета, но главный программист запрещает использовать подавляющее число нововведений из языка - чтобы консистентность со старым кодом (из времён .NET Framework 3.x, 4.x) сохранялась. Там же это, как его - догматы, что код должен по всему проекту быть по-возможности одинаковым. Я им, что с таким подходом этот проект будет вечно старьём, которое будет просто переводиться на новые рельсы (.NET 5, 6,...), но их возможности не исползовать. Там, где я на 3-5 строк пишу реализацию свойства по-новому, он расписывает на пол экрана в максимально старом стиле. Убивает читаемость кода в угоду глупой преемственности.
Кстати, новички, пришедшие на такой проект и обучавшиеся на новых версиях языка, скорее старый код меньше понимать будут, чем новый. Им будет просто непонятен смысл многословных простыней и кучи вложенных скобок там, где уже давно от этого можно было бы избавиться. Тут какой-то скрытый смысл умудрённых опытом мегасеньёров? - Нет, просто старпёры задеревенели и не хотят учить новое.
И все эти рутинные обязательные вызовы можно делать внутри себя.
мне, имеющему опыт с SQL, логично в конце всех операций сделать Commit SaveChanges()
Тебе же никто не запрещает переписать Dispose твоего контекста
Там, где я на 3-5 строк пишу реализацию свойства по-новому, он расписывает на пол экрана в максимально старом стиле.
Можно пример?
Ещё недавно же каблучок был?
Так ты же сначала именно про них и пел
Автобус всяко лучше утыканной сверху и сзади всякими грузовыми обвесами "малолитражки".
у меня так-то двухлитровый дизель
Обвес это 5 раз в год - крепление для велосипедов сзади.
А стальные 360 дней красивый компактный комфортный быстрый автомобиль
Куда спешить со всей семьёй? Я еду 120+- и мне хватает. Тем более, что на большинстве мест, особенно на австрийских и итальянских автобанах, больше 130 не разрешено.
А у меня "обвес" это каждые выходные с мая по сентябрь, плюс отпуска. В малолитражку внутрь он не лезет, и сзади не цепляется.
Тебе же никто не запрещает переписать Dispose твоего контекста
Мне никто не мешает хоть весь .NET переписать. Но ценится больше то, что хорошо работает из коробки.
Можно пример?
Я приводил уже. Сейчас все проекты закрыты, поэтому по-памяти примерно так:
его вариант
private MyType myObject; public MyType MyObject { get { if(myObject == null) { myObject = new MyType(); } инициализация myObject return myObject; } }
мой вариант
MyType myObject; public MyType MyObject => myObject ??= new() { инициализация myObject }
Или вот он говорит, чтобы я using обязательно использовал в старом стиле со скобочками (явное обозначение контекста), хотя без них всё проще и короче. И ещё несколько подобных моментов, которые вроде бы мелочь, но бесит, когда понимаешь, что можно проще, но нужно повторять шаг в шаг за дедками. А потому что в старых (15-летней давности) кусках кода так использовалось. Т.е. проект 15-летней давности нужно и через 10 лет от сегодняшнего дня писать как проект уже 25-летней давности. А то неконсистентно. То, что новый прогер, пришедший на проект, такую древность может уже и не понять - это консистентно.
Из этого можно сделать вывод, что для всех классов подобного типа не следует писать юнит тесты их просто следует называть интеграционными тестами.
1. Мы не про класс а про метод. Про конкретный метод. Из этого одного примера не надо делать далекоидущие выводы для каких-то "классов подобного типа".
2. Кого "их" называть? Тесты, которым для работы нужна БД? Да, их просто следует называть интеграционными.
Этот подход можно пользовать если мы хотим тестировать исключительно Query, а вот с Command будет посложнее, пусть даже база будет в локальном докере.
...Это самое малое что меня будет интересовать в данном случае. А вот загрузится ли полностью владелец или пользователи будет гораздо интереснее.
А если там еще и джойны есть, то есть что проверять.
Статическая база никак не подходит.
Это всё абсолютно не важно. Прилепил базу - прекращай называть тест "юнит-тестом". Ничего больше. Что сложного-то? А в своем интеграционном тесте можешь тестировать хоть джойны в докере, хоть простенькие селекты в in-memory.
По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость.
Вот класс, открываешь старый проект, а он вчера компилился, а сегодня уже нет.
Нет, просто старпёры задеревенели и не хотят учить ново
А вот не старпёр уже вовсю пользует primary constructor или всё же нет?
В чем преимущества вашего метода?
Метод не мой, всего лишь рекомендация руководящей партии - DbContext in dependency injection for ASP.NET Core
https://learn.microsoft.com/en-us/ef/core/dbcontext-config...
"It is generally better to inject the database context (MyDbContext) through the constructor rather than instantiating it directly within each method call. This approach follows the principle of dependency injection and allows for better testability and flexibility."
А приведенный вариант не очень гибкий как в вопросах тестирования, так и для модификации.
А если время жизни контекста и репозитория совпадают со временем жизни запроса, то отличий в функциональности пока не вижу.
Когда-то удобен var, когда то нет. В данном случае, мне больше нравится 1й.
Тут не удобство, а элементарная логика. Если с правой стороны объявлен тип, то с левой писать его ещё раз не имеет смысла. Ну кроме случаев полиморфизма. Но дать возможность не писать лишнее слово там, где это не нужно - нужно.
По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость.Вот класс, открываешь старый проект, а он вчера компилился, а сегодня уже нет.
Для этого есть необратимые конвертеры старого в новое. Куча программ так и работает - либо конвертим в новое, либо сидим на старой версии. Тот же Unity, многие пакеты 3D (и не только) моделирования. Да и сами языки некоторые идут по таким стопам. Вроде, Питон в каких-то версиях не совместим. Потом из мира веба - Ангуляр. У Яблока это вообще возведено в принцип работы - как с пользователями, так и с разработчиками (Swift).
Это лучше, чем копить мусор в языке. Если копить, рано или поздно придётся его похоронить. Или таки выпустить версию без совместимости и "начать с чистого листа".