Wpis z mikrobloga

#programowanie #csharp #webdev #bazydanych

Używał ktoś EF Core w połączeniu z npgsqlem jako code-first? Mam problem z relacją wiele-wiele.

https://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx

W tym przykładzie gość po prostu dorzucił wzajemne kolekcje i framework sam wykminił aby sobie zrobić table łączące, nawet bez drutowania niczego w model builderze. No ale domyślam się że to w użyciu z MSSQL a nie PostgreSQL.

U mnie jak wrzuciłem tylko wzajemne kolekcje, to EF rzygał, że nie wie o co mi chodzi ("Unable to determine the relationship represented by navigation property"). Jak dokonfigurowałem modelBuilder w taki sposób: https://pastebin.com/fWng6uTp ,
to mi pododawał sztuczne id tylko zamiast stworzyć tabele łączące ( ͡° ʖ̯ ͡°) Problem w tym, że on w drugim przykładzie miał możliwość ustawienia relacji .HasMany(x).WithMany(y) a u mnie jest tylko .HasMany(x).WithOne(y) i prawdopodobnie dlatego się posypało, bo nie byłem w stanie tego odpowiednio zdefiniować.
  • 29
@teddybear69: Nie zgadłeś. Po prostu są tu ludzie którzy takie rzeczy robili, bo już z nimi gadałem i może będą wiedzieć o co chodzi bez tworzenia wpisu na stacku, gdzie jest to mniej wygodne. Dopiero jak tutaj nikt nie będzie wiedział o co chodzi to pójdę na SO.
@Czesiowcy: Rozumiem że mam ręcznie migrację edytować? Ale cholera to będzie mocno niewygodne w dłuższej perspektywie. Many-to-many to bardzo częsta relacja a ORM jest od tego aby było szybko i prosto ( ͡° ʖ̯ ͡°)
@Khaine: nie musisz, stwórz dodatkowy model encji reprezentujący relację many to many. Google Twoim przyjacielem - sorry, jestem daleko od jakiegokolwiek komputera w chwili obecnej. Ewentualnie użyj EF Core 3.0, o ile mi wiadomo, obecnych release'ów można używać produkcyjnie
@Czesiowcy: Hmm, ten 3.0 jest pod netstandard2.1 i chyba nie zadziała pod netcoreapp2.2 ( ͡° ʖ̯ ͡°) Nie orientuję się za bardzo w core misz-maszu, da się to jakiś zgrać?
via Wykop Mobilny (Android)
  • 1
@Khaine: netcore 3 implementuje .netstandard 2.1 jakby co. Ogólnie wszystke .netowe implementacje (.net framework, mono, core) dążą żeby mieć zaimplementowany .netstandard. Oczywiście potrzebują czasu żeby to zrobić a nawet finalnie okazuje się że niektóre rzeczy na niektórych platformach są dostępne ale w środku siedzi NotImplementedException
@Khaine:

Są dwie drogi

a) framework sam za ciebie to jebnie

b) sam musisz to jebnąć

przy b trik polega na tym, że jak już trochę sam zaczniesz mieszać, to już do końca musisz sam jebnąć to z ręki (relacje), przynajmniej mi się raz tak stało gdy ładowałem definicje relacji z innego assembly, bo gdy definiowałem w contexcie to jeszcze się nie rzucał

Jeżeli chcesz zrobić many2mant, to musisz #!$%@?ąć tabelę
via Wykop Mobilny (Android)
  • 0
@ZaoSan: dokładnie w ten sposób to zrobiłem. Natomiast zapytania potem nieco bolą, bo trzeba robić joiny przez LINQ. Aczkolwiek nie jest źle. Bardziej mnie zastanawia ile wydajności stracimy, bo przy jednym wierszu fetchowanym przy 4 krotnyn joinie LINQ zajmował ok 460 ms vs raw SQL około 400.

Pytanie co przy paru tysiącach przykładowo.
@Khaine

Natomiast zapytania potem nieco bolą, bo trzeba robić joiny przez LINQ.


wtf?

.Include(x => property1)
.ThenInclude(x => x.SomeProperty) - jest bug w intellisense visual studio, że nie podpowiada tej lambdy, ale ona działa.

Pytanie co przy paru tysiącach przykładowo.


Paginacja.

Bardziej mnie zastanawia ile wydajności stracimy, bo przy jednym wierszu fetchowanym przy 4 krotnyn joinie LINQ zajmował ok 460 ms vs raw SQL około 400.


To mi się wydaje podejrzane, bo
Paginacja.


@ZaoSan: Tak, wszystko da się w paginację wsadzić xD No tego akurat się nie da, bo zapytanie z definicji ma zwracać wszystko i dlatego się zastanawiam ile wydajności się straci.
@ZaoSan: Ja to robiłem LINQ way:

var permissions = from u in Users
join ur in UserRoles on u.Id equals ur.UserId
join r in Roles on ur.RoleId equals r.Id
join rp in RolePermissions on r.Id equals rp.RoleId
join p in Permissions on rp.PermissionId equals p.Id
where u.Id == 1
select p;

Działa i traci tyle ile pisałem. Tylko zastanawia mnie czy strata jest jednorazowa bo wynika z jednorazowego zlepienia SQLa z
@ZaoSan: No właśnie nie. Jeden rekord. Ale tyle jest przy pierwszym odpaleniu, potem szybciej bo sobie optymalizuje (a raczej cache'uje), więc ledwo 30 ms (i jedno i drugie trwa wtedy tyle samo). Z tego co podejrzałem to EF tam nałożył indeksy, więc nie wiem czy da radę szybciej. Jeszcze w grę może wchodzić jakieś leniwe tworzenie obiektów pod spodem i dlatego pierwsze odpalenie tak długo trwa. Raw SQL jest ledwo 60
@ZaoSan: No mam generalnie podobne zdanie. To drugie zapytanie w raw SQL jest przez Dapper, więc odpada parsowanie LINQ. Później jedno i drugie ma takie same czasy, ale pytam cały czas o to samo a bazy danych to podstępne #!$%@? ( ͡º ͜ʖ͡º) Entity zresztą też ma jakieś triki po swojej stronie zaszyte i pewnie jak się pyta po kilka razy o to samo, to też
@ZaoSan: Bazy potrafią różne sztuczki robić. Optymalizują sobie choćby w taki sposób, że ładują do RAMu dane na podstawie statystyk więc siłą rzeczy kolejne zapytania o to samo będą szybsze.
no to baza, a ja pisałem odnośnie twojego:

Entity zresztą też ma jakieś triki po swojej stronie zaszyte i pewnie jak się pyta po kilka razy o to samo, to też sobie gdzieś z boku trzyma.