Deutsch

Непонятки с EF

2034  1 2 3 4 все
alex445 коренной житель27.12.23 01:21
NEW 27.12.23 01:21 
в ответ AlexNek 26.12.23 23:33, Последний раз изменено 27.12.23 01:31 (alex445)

this нужен лишь в проперти или в конструкторе. Один раз на весь класс. В остальных 10-20 случаях я лучше не буду тянуться до _, тем более, что чтобы в неё попасть, нужно постоянно в неё целиться. Даже если владеешь слепой печатью на английском - всё равно неудобно.

#21 
alex445 коренной житель27.12.23 01:23
NEW 27.12.23 01:23 
в ответ Срыв покровов 26.12.23 23:57

void DeleteUserById(int id)

{
using (var context = new MyDbContext())

context.Users.Remove(x => x.Id == id);

context.SaveChanges();

}

А почему SaveChanges не вызывается автоматически при выходе за пределы контекста MyDbContext? Заставляют писать лишнюю, но очевидную строчку кода.

#22 
alex445 коренной житель27.12.23 01:24
NEW 27.12.23 01:24 
в ответ Срыв покровов 26.12.23 23:57, Последний раз изменено 27.12.23 01:34 (alex445)
using (var context = new MyDbContext())
using (MyDbContext context = new())

Второй вариант лучше. В первом варианте var не несёт никакого смысла и просто семантический мусор. Я бы на месте создателей Шарпа позволил бы в таких конструкциях вообще не писать ничего перед context.

#23 
alex445 коренной житель27.12.23 01:28
NEW 27.12.23 01:28 
в ответ Срыв покровов 26.12.23 23:57, Последний раз изменено 27.12.23 01:35 (alex445)
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, а потом ещё и юнит-тестируете их, вы просто душнилы. ))

#24 
Срыв покровов патриот27.12.23 08:28
27.12.23 08:28 
в ответ alex445 27.12.23 01:23
А почему SaveChanges не вызывается автоматически при выходе за пределы контекста MyDbContext?

Ну например потому что ты из контекста мог только выбирать данные (select).

#25 
Срыв покровов патриот27.12.23 08:31
NEW 27.12.23 08:31 
в ответ alex445 27.12.23 01:28

Душнила 2 года подряд ноет на автофоруме, что для него не сделали подхядящий электрический автобус.

#26 
alex445 коренной житель27.12.23 09:59
NEW 27.12.23 09:59 
в ответ Срыв покровов 27.12.23 08:28, Последний раз изменено 27.12.23 10:05 (alex445)
Ну например потому что ты из контекста мог только выбирать данные (select).

Не в этом суть. То, что в контексте лишь выборка идёт, сам контекст прекрасно знает. Почему бы ему внутри себя не вызывать автоматом сохранение изменений при выходе за пределы контекста, если там кроме выборки ещё что-то изменилось? Ведь подавляющая часть сценариев - создали контекст, что-то сделали, сохранили изменения, вышли за предел. И все эти рутинные обязательные вызовы можно делать внутри себя.


Вот почему-то от ручного вызова Dispose каждый раз они нас избавили, от сохранения контекста - нет. Короче, там ещё улучшать и улучшать. Сишарп страдает от того, что слишком быстро идёт вперёд, но старьё не чистит. В результате в языке много мусора, в том числе синтаксического. По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость. Эта совместимость по большому счёту не нужна. Например, на моём проекте хоть и новый код и новые проекты в солюшене пишутся на новых версиях дотнета, но главный программист запрещает использовать подавляющее число нововведений из языка - чтобы консистентность со старым кодом (из времён .NET Framework 3.x, 4.x) сохранялась. Там же это, как его - догматы, что код должен по всему проекту быть по-возможности одинаковым. Я им, что с таким подходом этот проект будет вечно старьём, которое будет просто переводиться на новые рельсы (.NET 5, 6,...), но их возможности не исползовать. Там, где я на 3-5 строк пишу реализацию свойства по-новому, он расписывает на пол экрана в максимально старом стиле. Убивает читаемость кода в угоду глупой преемственности.


Кстати, новички, пришедшие на такой проект и обучавшиеся на новых версиях языка, скорее старый код меньше понимать будут, чем новый. Им будет просто непонятен смысл многословных простыней и кучи вложенных скобок там, где уже давно от этого можно было бы избавиться. Тут какой-то скрытый смысл умудрённых опытом мегасеньёров? - Нет, просто старпёры задеревенели и не хотят учить новое.

#27 
alex445 коренной житель27.12.23 10:02
NEW 27.12.23 10:02 
в ответ Срыв покровов 27.12.23 08:31
Душнила 2 года подряд ноет на автофоруме, что для него не сделали подхядящий электрический автобус.

Ещё недавно же каблучок был?


Автобус всяко лучше утыканной сверху и сзади всякими грузовыми обвесами "малолитражки".

#28 
Срыв покровов патриот27.12.23 10:59
NEW 27.12.23 10:59 
в ответ alex445 27.12.23 09:59
И все эти рутинные обязательные вызовы можно делать внутри себя.

мне, имеющему опыт с SQL, логично в конце всех операций сделать Commit SaveChanges()

Тебе же никто не запрещает переписать Dispose твоего контекста

Там, где я на 3-5 строк пишу реализацию свойства по-новому, он расписывает на пол экрана в максимально старом стиле.

Можно пример?

#29 
Срыв покровов патриот27.12.23 11:04
NEW 27.12.23 11:04 
в ответ alex445 27.12.23 10:02
Ещё недавно же каблучок был?

Так ты же сначала именно про них и пел

Автобус всяко лучше утыканной сверху и сзади всякими грузовыми обвесами "малолитражки".

у меня так-то двухлитровый дизель

Обвес это 5 раз в год - крепление для велосипедов сзади.
А стальные 360 дней красивый компактный комфортный быстрый автомобиль

#30 
alex445 коренной житель27.12.23 11:12
NEW 27.12.23 11:12 
в ответ Срыв покровов 27.12.23 11:04

Куда спешить со всей семьёй? Я еду 120+- и мне хватает. Тем более, что на большинстве мест, особенно на австрийских и итальянских автобанах, больше 130 не разрешено.


А у меня "обвес" это каждые выходные с мая по сентябрь, плюс отпуска. В малолитражку внутрь он не лезет, и сзади не цепляется.

#31 
alex445 коренной житель27.12.23 11:23
NEW 27.12.23 11:23 
в ответ Срыв покровов 27.12.23 10:59, Последний раз изменено 27.12.23 11:31 (alex445)
Тебе же никто не запрещает переписать 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
}
#32 
alex445 коренной житель27.12.23 11:27
NEW 27.12.23 11:27 
в ответ alex445 27.12.23 11:23, Последний раз изменено 27.12.23 11:28 (alex445)

Или вот он говорит, чтобы я using обязательно использовал в старом стиле со скобочками (явное обозначение контекста), хотя без них всё проще и короче. И ещё несколько подобных моментов, которые вроде бы мелочь, но бесит, когда понимаешь, что можно проще, но нужно повторять шаг в шаг за дедками. А потому что в старых (15-летней давности) кусках кода так использовалось. Т.е. проект 15-летней давности нужно и через 10 лет от сегодняшнего дня писать как проект уже 25-летней давности. А то неконсистентно. То, что новый прогер, пришедший на проект, такую древность может уже и не понять - это консистентно.

#33 
AlexNek патриот27.12.23 12:01
AlexNek
NEW 27.12.23 12:01 
в ответ alex445 27.12.23 01:21
я лучше не буду тянуться до _

Не вижу никаких, проблем - всё на автомате.

Но дискутировать по поводу code style смысла особого не имеет, у каждой команды свои соглашения и хотя не все с ними согласны, нужно делать как договорились.


#34 
MrSanders коренной житель27.12.23 12:03
NEW 27.12.23 12:03 
в ответ AlexNek 26.12.23 21:55
Из этого можно сделать вывод, что для всех классов подобного типа не следует писать юнит тесты их просто следует называть интеграционными тестами.

1. Мы не про класс а про метод. Про конкретный метод. Из этого одного примера не надо делать далекоидущие выводы для каких-то "классов подобного типа".

2. Кого "их" называть? Тесты, которым для работы нужна БД? Да, их просто следует называть интеграционными.

Этот подход можно пользовать если мы хотим тестировать исключительно Query, а вот с Command будет посложнее, пусть даже база будет в локальном докере.
...

Это самое малое что меня будет интересовать в данном случае. А вот загрузится ли полностью владелец или пользователи будет гораздо интереснее.

А если там еще и джойны есть, то есть что проверять.

Статическая база никак не подходит.

Это всё абсолютно не важно. Прилепил базу - прекращай называть тест "юнит-тестом". Ничего больше. Что сложного-то? А в своем интеграционном тесте можешь тестировать хоть джойны в докере, хоть простенькие селекты в in-memory.


#35 
AlexNek патриот27.12.23 12:04
AlexNek
NEW 27.12.23 12:04 
в ответ alex445 27.12.23 01:24
using (var context = new MyDbContext())
using (MyDbContext context = new())

>Второй вариант лучше

Можно спорить до потери сознания и каждый останется при своем мнении.

Когда-то удобен var, когда то нет. В данном случае, мне больше нравится 1й.

#36 
AlexNek патриот27.12.23 12:11
AlexNek
NEW 27.12.23 12:11 
в ответ alex445 27.12.23 09:59
По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость.

Вот класс, открываешь старый проект, а он вчера компилился, а сегодня уже нет.


Нет, просто старпёры задеревенели и не хотят учить ново

А вот не старпёр уже вовсю пользует primary constructor или всё же нет?

#37 
AlexNek патриот27.12.23 12:25
AlexNek
NEW 27.12.23 12:25 
в ответ Срыв покровов 26.12.23 23:57
В чем преимущества вашего метода?

Метод не мой, всего лишь рекомендация руководящей партии - 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."


А приведенный вариант не очень гибкий как в вопросах тестирования, так и для модификации.

А если время жизни контекста и репозитория совпадают со временем жизни запроса, то отличий в функциональности пока не вижу.

#38 
alex445 коренной житель27.12.23 12:27
NEW 27.12.23 12:27 
в ответ AlexNek 27.12.23 12:04
Когда-то удобен var, когда то нет. В данном случае, мне больше нравится 1й.

Тут не удобство, а элементарная логика. Если с правой стороны объявлен тип, то с левой писать его ещё раз не имеет смысла. Ну кроме случаев полиморфизма. Но дать возможность не писать лишнее слово там, где это не нужно - нужно.

#39 
alex445 коренной житель27.12.23 12:33
NEW 27.12.23 12:33 
в ответ AlexNek 27.12.23 12:11
По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость.

Вот класс, открываешь старый проект, а он вчера компилился, а сегодня уже нет.

Для этого есть необратимые конвертеры старого в новое. Куча программ так и работает - либо конвертим в новое, либо сидим на старой версии. Тот же Unity, многие пакеты 3D (и не только) моделирования. Да и сами языки некоторые идут по таким стопам. Вроде, Питон в каких-то версиях не совместим. Потом из мира веба - Ангуляр. У Яблока это вообще возведено в принцип работы - как с пользователями, так и с разработчиками (Swift).


Это лучше, чем копить мусор в языке. Если копить, рано или поздно придётся его похоронить. Или таки выпустить версию без совместимости и "начать с чистого листа".

#40 
1 2 3 4 все