Skocz do zawartości
Tartar

[C#][linq] Problem z left join

Rekomendowane odpowiedzi

Witam

Mam problem ze zrobieniem left join'a w linq.

Chcę połączyć te dwa DataTable:

dt_JOINOEZAM.Columns.Add("NAJ_OE_TOW", typeof(string)); 
dt_JOINOEZAM.Columns.Add("ID_TOW", typeof(int)); 
dt_JOINOEZAM.Columns.Add("ID_TOWZAM1", typeof(int));
dt_JOINOEZAM.Columns.Add("ID_TOWZAM2", typeof(int)); 
dt_JOINOEZAM.Columns.Add("ID_TOW_DO", typeof(int)); 
dt_JOINOEZAM.Columns.Add("NAJ_OE_ZAM", typeof(string)); 
/*ta niżej ma być połączona w lewo do tej powyżej*/
dt_F_Varchar.Columns.Add("ID_X1", typeof(int)); 
dt_F_Varchar.Columns.Add("ID_X2", typeof(int));
dt_F_Varchar.Columns.Add("ID_F_VARCHAR1", typeof(int)); 
dt_F_Varchar.Columns.Add("ID_F_VARCHAR2", typeof(int)); 
dt_F_Varchar.Columns.Add("WARTOSC", typeof(string));

 

Wynik ma trafić do tabeli jak niżej:

dt_KONCOWA.Columns.Add("NAJ_OE_TOW", typeof(string));
dt_KONCOWA.Columns.Add("ID_TOW", typeof(int));
dt_KONCOWA.Columns.Add("ID_TOWZAM1", typeof(int));
dt_KONCOWA.Columns.Add("ID_TOWZAM2", typeof(int));
dt_KONCOWA.Columns.Add("ID_TOW_DO", typeof(int));
dt_KONCOWA.Columns.Add("NAJ_OE_ZAM", typeof(string));
dt_KONCOWA.Columns.Add("ID_F_VARCHAR1", typeof(int));
dt_KONCOWA.Columns.Add("ID_F_VARCHAR2", typeof(int));
dt_KONCOWA.Columns.Add("WARTOSC", typeof(string));

 

Tutaj jest kod tego połączenia (nie jestem dobry w linqu więc mogłem coś sknocić - zrobiłem to na podstawie danych z neta):

var query = (from d1 in dt_JOINOEZAM.AsEnumerable()
	join d2 in dt_F_Varchar.AsEnumerable()
	on new { A = d1.Field<int>("ID_TOWZAM2"), B = d1.Field<int>("ID_TOWZAM1") } equals new { A = d2.Field<int>("ID_X2"), B = d2.Field<int>("ID_X1") }
	into grupaKoncowa
	from d in grupaKoncowa.DefaultIfEmpty()
	select new
	{
	NAJ_OE_TOW = d1.Field<string>("NAJ_OE_TOW"),
	ID_TOW = d1.Field<int>("ID_TOW"),
	ID_TOWZAM1 = d1.Field<int>("ID_TOWZAM1"),
	ID_TOWZAM2 = d1.Field<int>("ID_TOWZAM2"),
	ID_TOW_DO = d1.Field<int>("ID_TOW_DO"),
	NAJ_OE_ZAM = d1.Field<string>("NAJ_OE_ZAM"),
	ID_F_VARCHAR1 = d.Field<int?>("ID_F_VARCHAR1") == null ? -1000 : d.Field<int>("ID_F_VARCHAR1"),
	ID_F_VARCHAR2 = d.Field<int?>("ID_F_VARCHAR2") == null ? -1000 : d.Field<int>("ID_F_VARCHAR2"),
	WARTOSC = d.Field<string>("WARTOSC") ?? ""
	}).AsQueryable();

var qSel = from q in query
	select dt_KONCOWA.LoadDataRow(new object[]
	{
	q.NAJ_OE_TOW,
	q.ID_TOW,
	q.ID_TOWZAM1,
	q.ID_TOWZAM2,
	q.ID_TOW_DO,
	q.NAJ_OE_ZAM,
	q.ID_F_VARCHAR1,
	q.ID_F_VARCHAR2,
	q.WARTOSC
	}, false);
dt_KONCOWA = qSel.CopyToDataTable();

 

Przy takim kodzie dla pierwszego zapytania dostaję taki błąd:

System.ArgumentNullException: Wartość nie może być zerowa.

Nazwa parametru: row

w System.Data.DataRowExtensions.Field[T](DataRow row, String columnName)

w NocnyBilans.MainForm.<>c.<Lacz_VARCHAR>b__31_7(<>f__AnonymousType1`2 <>h__TransparentIdentifier0, DataRow d) w C:\Users\XRay\source\repos\NocnyBilans\NocnyBilans\MainForm.cs:wiersz 503

w System.Linq.Enumerable.<SelectManyIterator>d__23`3.MoveNext()

w System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()

w System.Data.DataTableExtensions.LoadTableFromEnumerable[T](IEnumerable`1 source, DataTable table, Nullable`1 options, FillErrorEventHandler errorHandler)

w System.Data.DataTableExtensions.CopyToDataTable[T](IEnumerable`1 source)

w NocnyBilans.MainForm.Lacz_VARCHAR(DataTable dt_joinoezam, DataTable dt_varchar, DataTable dt_wynik, Stopwatch czas_wykonania) w C:\Users\XRay\source\repos\NocnyBilans\NocnyBilans\MainForm.cs:wiersz 529

Wiersz 503 to "select new", wiersz 529 to "dt_KONCOWA = qSel.CopyToDataTable();".

Jak nie dam tego

ID_F_VARCHAR1 = d.Field<int?>("ID_F_VARCHAR1") == null ? -1000 : d.Field<int>("ID_F_VARCHAR1"),

ID_F_VARCHAR2 = d.Field<int?>("ID_F_VARCHAR2") == null ? -1000 : d.Field<int>("ID_F_VARCHAR2"),

WARTOSC = d.Field<string>("WARTOSC") ?? ""

to wszystko jest OK, jednak jak dam tylko np.: ID_F_VARCHAR1 = d.Field<int>("ID_F_VARCHAR1") to od razu błąd.

 

Zrobiłem "małe" obejście tego problemu jednak nie wiem ile na tym stracę czasowo i mocowo:

foreach (DataRow dr in dt_joinoezam.Rows)
{
	string warunek = string.Format("ID_X1 = {0} AND ID_X2 = {1}", dr["ID_TOWZAM1"], dr["ID_TOWZAM2"]);
	DataRow[] selWynik = dt_varchar.Select(warunek);
	if (selWynik.Length == 0)
	{
	dt_wynik.Rows.Add(dr["NAJ_OE_TOW"], dr["ID_TOW"], dr["ID_TOWZAM1"], dr["ID_TOWZAM2"], dr["ID_TOW_DO"], dr["NAJ_OE_ZAM"], -1000, -1000, "");
	}
	else
	{
	dt_wynik.Rows.Add(dr["NAJ_OE_TOW"], dr["ID_TOW"], dr["ID_TOWZAM1"], dr["ID_TOWZAM2"], dr["ID_TOW_DO"], dr["NAJ_OE_ZAM"], selWynik[0]["ID_F_VARCHAR1"], selWynik[0]["ID_F_VARCHAR2"], selWynik[0]["WARTOSC"]);
	}
}

 

Obecne ilości wierszy w tabelach to (to tylko wycinek danych na których program będzie pracował - dlatego zależy mi na zoptymalizowaniu go):

dt_JOINOEZAM=3917,

dt_F_Varchar=259882,

dt_KONCOWA=3917.

Ilości te będą znacznie większe.

 

Drugie pytanie mniej ważne (ale do statystyk programu potrzebne - optymalizacja bo komp docelowy ze znacznie mniejszą pamięcią RAM będzie) - po każdej funkcji robię process.WorkingSet64 co niby ma mi dać zajętość aktualnego procesu. Problemem jest to że dane te są cały czas takie same i nie wiem jak się zmienia zajętość pamięci po dołożeniu danych do tabel.

 

Z góry dziękuję.

 

Wesołych Świąt a przede wszystkim dużo Zdrowia życzę.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

  • Tematy

  • Odpowiedzi

    • CPU: Intel i9-13900KS Płyta: ASRock Z790 NOVA RAM: Lexar Ares DDR5, 2x16GB (LD5U16G72C34LA-RGD) Zasilacz: Corsair HX1000i(2023) Gdy odpalam test Linpack AMD64 w OCCT, test zawiesza się za każdym razem. W dzienniku zdarzeń pokazuje się zawsze błąd 0xc0000005 dla linpack.exe z tym samym offsetem 0x000000000000f5d4. Co ciekawe gdy wyłączę jeden E-Core lub jeden wątek HT wtedy test przechodzi bez problemu. Tutaj jest wyciągnięty sam program Linpack (uruchamiany przez start.bat): https://buzzheavier.com/f/GLcs1hZGkAA= Testowałem na OCCT w wersji 12.1.18. Windows 10. Miałbym prośbę aby osoby z procesorami o 32 wątkach np. 13900XX/14900XX odpaliły u siebie test i dały znać czy u nich też występuje ten błąd. Bezpośrednie uruchomienie Linpack ukazuje więcej informacji o tym co się dzieje. Program uruchamia się, ale zawiesza przy rozpoczynaniu obliczeń. W BIOSie wyłączanie XMP, wyłączanie Turbo, ustawianie PL1=150W, PL2=253W, ICCMax=307 nie pomaga. Crash przy 32 wątkach: d:\LINPACKK>linpack.exe linpack-occt Intel(R) LINPACK data - OCCT Current date/time: Tue Apr 18 15:17:50 2024 CPU frequency: 3.187 GHz Number of CPUs: 32 Number of threads: 32 Parameters are set to: Number of tests : 1 Number of equations to solve (problem size) : 4094 Leading dimension of array : 4094 Number of trials to run : 99999999 Data alignment value (in Kbytes) : 4 Maximum memory requested that can be used = 134172664, at the size = 4094 ============= Timing linear equation system solver ================= Size LDA Align. Time(s) GFlops Residual Residual(norm) d:\LINPACKK> Działa normalnie przy 31 wątkach. d:\LINPACKK>linpack.exe linpack-occt Intel(R) LINPACK data - OCCT Current date/time: Tue Apr 18 17:55:12 2024 CPU frequency: 3.187 GHz Number of CPUs: 31 Number of threads: 31 Parameters are set to: Number of tests : 1 Number of equations to solve (problem size) : 4094 Leading dimension of array : 4094 Number of trials to run : 99999999 Data alignment value (in Kbytes) : 4 Maximum memory requested that can be used = 134172664, at the size = 4094 ============= Timing linear equation system solver ================= Size LDA Align. Time(s) GFlops Residual Residual(norm) 4094 4094 4 0.190 240.9350 1.525602e-011 3.164964e-002 4094 4094 4 0.186 245.9882 1.525602e-011 3.164964e-002 4094 4094 4 0.179 255.9760 1.525602e-011 3.164964e-002 4094 4094 4 0.186 246.6407 1.525602e-011 3.164964e-002    
    • Czołem Szykuje się powoli na zmianę laptoka, obecnie mam della 7567 z 1050 Ti który już swoje przeszedł i zastanawiam się nad przesiadką na coś nowszego.  Moje pierwsze pytanie jest takie, przy budżecie 4-5k zł, gdybym jednak nie chciał brać gamingowego laptopa w tej cenie, to co właściwie zyskuje? Poza tym że nie będę mógł na nim grać oczywiście xD Tak myślę czy by może nie odpuścić sobie grania na pc i zamiast tego kupić xboxa i wybrac tańszego laptopa, bo w sumie nie gram już tyle co kiedyś, no i nie musze się martwić na konsoli czy mi coś odpali czy nie.  Gdyby jednak padło na laptopa to fajnie jakby miał: - ładny, jasny i porządny ekran 14-15 cali (największy minus mojego obecnego della to właśnie dość gówniany i taki blady ekran, nie chciałbym już tego powtórzyć) - 16 giga ramu, ssd 512 gb - taki standardzik raczej - grafika - na co mogę w ogóle liczyć w takiej cenie? RTX 4060?  - co procesora to nie mam obecnie pojęcia co byłoby ok, a co nie, tutaj potrzebuje pomocy w doborze czegoś sensownego - system już zainstalowany, może być win 11 może być 10 wszystko jedno w sumie - co do baterii nie mam jakichś wielkich wymogów, fajnie jakby była dobra, jak będzie powiedzmy przeciętna to też ok - na plus będzie dobre wykonanie, jakiejś aluminium czy coś, jak plastik to fajnie żeby był porządny.  Chyba tyle, jeszcze może dobre głośniki byłyby mile widziane bo nie mam specjalnie miejsca na zewnętrzne, mój obecny dell ma je całkiem ok.   
    • Jak masz miejsce na 140mm i chcesz tylko dwie sztuki, to wrzuć tam najlepiej Arctic P14. TANIE, nieco grubsze i bardzo wydajne z przeszkadzajkami. Fluctusa do tej budy na ssanie nie dawaj. Na pchanie powinien sobie radzić. Tylko dalej wolałbym P14 Arctica 
    • Trailer bieda, chwalą się rzeczami które powinny być zrobione parę lat temu. Podtrzymuję, nie dam im zarobić pierwszy raz od 15 lat.
    • Dzięki, zaplanuję to sobie jakoś sprytnie, żeby jak najwięcej objechać w 2-3 dni. Katarzyna Niewiadoma wygrała Walońską Strzałę. 😃 W końcu, po 5 latach oczekiwania na kolejne zawodowe zwycięstwo, zmogła rywalki pięknym atakiem na kultowej ściance Mur de Huy. A było co podjeżdżać, bo ten piekielny kawałek od lat pokonuje najlepszych zawodników tej dyscypliny: Długość: 1 300 m Nachylenie: AV: 9,3%, MAX: 26% Przewyższenie: 120 m Wysokość: 240 m Cieszyłem się jak dziecko podczas transmisji, po drugim miejscu we Flandrii, wygrana wisiała w powietrzu.
  • Aktywni użytkownicy

×
×
  • Dodaj nową pozycję...