[C#] SqlDataReader en IDataRecord

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
Ik ben voor zelfstudie bezig met wat datalaag technische dingetjes. Nou loop ik tegen het volgende aan:

Ik heb een query die een aantal velden terug geeft. 1 van deze velden is een userid maar die hoeft niet altijd gevuld te zijn. Indien dit veld namelijk niet gevuld is gaat het hier om een gast dus haal ik in mijn query ook guestname op.
Nu wil ik 1 veld in mijn IDataRecord List hebben namelijk UserName, deze moet indien userid NULL is guestname gebruiken. Indien userid niet leeg is moet ik eigenlijk door middel van een functie ofzo de username ophalen die in de user tabel staat. De vraag is of dit een denkfout is en ik dit op een andere manier moet doen of als het wel zo kan hoe ik dit dan moet doen? Heb even een zetje in de goede richting nodig.

Code so far:

C#:
1
2
3
4
5
6
7
8
using (var reader = cmd.ExecuteReader())
                        return reader.Cast<IDataRecord>()
                            .Select(x => new MessageInfo()
                            {
                                UserName = x.GetString(0),
                                Line = x.GetString(1),
                                RecordedDate = x.GetDateTime(2)
                            }).ToList();


In dit geval is x.GetString(0) alleen guestname kolom omdat ik verder wou en dus nog niet wist hoe ik dit moest doen.

Ps. Ik kan dit in mijn query niet afvangen omdat ik gebruik maken van sqldependency query en die staat zo weinig toe dat ik niet zie hoe ik dit zou moeten doen. dus isnull, coalesce, computed kolom kan ik niet gebruiken...

edit:
Sorry voor de immens vage titel maar dat reflecteert wel in hoeverre ik geen idee heb

[ Voor 3% gewijzigd door maxtz0r op 30-04-2014 17:01 ]

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 03:43
Zoiets?
C#:
1
UserName = x.GetString(0) == null ? x.GetString(1) : x.GetString(2)

Waar bij
1 = userid
2 = guestname
3 = username

Geen wonder van schoonheid maar zal wel werken.

Wat ik me alleen afvraag is hoe je een guestname kan weten als het om een gast gaat?

[ Voor 18% gewijzigd door sig69 op 30-04-2014 17:10 ]

Roomba E5 te koop


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
sig69 schreef op woensdag 30 april 2014 @ 17:09:
Zoiets?
C#:
1
UserName = x.GetString(0) == null ? x.GetString(1) : x.GetString(2)

Waar bij
1 = userid
2 = guestname
3 = username

Geen wonder van schoonheid maar zal wel werken.

Wat ik me alleen afvraag is hoe je een guestname kan weten als het om een gast gaat?
Het is een soort log waarbij in 1 regel staat userid (kan dus waarde hebben maar ook null zijn), GuestName(kan dus waarde hebben maar ook null zijn), loginformatie. Ik heb dus of userid of guestname.

Op zich ziet jou oplossing er goed uit alleen heb ik username dus niet en moet ik die dus via een functie eerst ophalen. Zou ik dan dit kunnen doen?
C#:
1
UserName = x.GetString(0) == null ? x.GetString(1) : GetUsername(x.GetString(0)) 

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 03:43
Zou kunnen, maar het is misschien efficiënter om username meteen in je query mee te nemen dmv een join ofzo

Roomba E5 te koop


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
sig69 schreef op woensdag 30 april 2014 @ 17:09:
Zoiets?
C#:
1
UserName = x.GetString(0) == null ? x.GetString(1) : x.GetString(2)
offtopic:
Ik kan me vergissen, maar moet je niet comparen met DBNull.Value i.p.v. met null? Is alweer even geleden :P

[ Voor 18% gewijzigd door RobIII op 30-04-2014 19:01 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
RobIII schreef op woensdag 30 april 2014 @ 19:01:
[...]

offtopic:
Ik kan me vergissen, maar moet je niet comparen met DBNull.Value i.p.v. met null? Is alweer even geleden :P
Naast dat is er ook een method IsDbNull() waarmee je kunt kijken of een waarde null is of niet.

Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
sig69 schreef op woensdag 30 april 2014 @ 18:06:
Zou kunnen, maar het is misschien efficiënter om username meteen in je query mee te nemen dmv een join ofzo
Omdat dit een notification query is ging ik er eigenlijk vanuit dat dit niet mogelijk is. Echter na het lezen van: http://technet.microsoft..../ms181122(v=sql.105).aspx lijkt het dat alleen outer-joins en self-joins niet mag. Ik heb nu een left join gebruikt alleen krijg nog wel exceptions en het vervelende dan is dat iedere keer mijn onchange() afgaat. Dus nog even puzzelen waarom deze query niet werkt.

Mocht iemand het direct zien:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Query chatlog to get latest messages of last 5 hours 
                using (SqlCommand cmd = new SqlCommand(@"Select [Name],[GuestName],[Line],[Recorded] FROM [ws].[chatlog] left join [dbo].[mp_users] on [dbo].[mp_users].[UserID] = [ws].[chatlog].[UserId] where [RoomName] is null AND [Recorded] >  @d ORDER BY [Recorded] asc", connection))
                {
                    cmd.Notification = null;
                    cmd.Parameters.Add(new SqlParameter("@d", currentdate));

                    SqlDependency dependency = new SqlDependency(cmd);
                    dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);

                    if (connection.State == ConnectionState.Closed)
                        connection.Open();

                    using (var reader = cmd.ExecuteReader())
                        return reader.Cast<IDataRecord>()
                            .Select(x => new MessageInfo()
                            {
                                UserName = x.GetValue(0) == System.DBNull.Value ? x.GetString(1) : x.GetString(0),
                                Line = x.GetString(2),
                                RecordedDate = x.GetDateTime(3)
                            }).ToList();
                }
RobIII schreef op woensdag 30 april 2014 @ 19:01:
[...]

offtopic:
Ik kan me vergissen, maar moet je niet comparen met DBNull.Value i.p.v. met null? Is alweer even geleden :P
Klopt!

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
maxtz0r schreef op woensdag 30 april 2014 @ 19:49:
Omdat dit een notification query is ging ik er eigenlijk vanuit dat dit niet mogelijk is.
Dat was wel zo handig geweest dat even in je topicstart te vermelden ;) O-)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
RobIII schreef op woensdag 30 april 2014 @ 20:04:
[...]

Dat was wel zo handig geweest dat even in je topicstart te vermelden ;) O-)
Ik heb dat in mijn PS. staan alleen zie dat ik het daar in mijn verwarring sqldependency query heb genoemd inplaats van notification query.

De exception die ik krijg heeft als "source" Object, zie: MSDN: SqlNotificationSource Enumeration (System.Data.SqlClient)

Ik heb alleen geen object wijzigingen gedaan naar mijn idee dus ik snap deze foutmelding voor geen moer...

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
'ik krijg exceptions' maar je vermeldt niet welke, wat het onmogelijk maakt je vraag te beantwoorden.

Je username test kun je ook in de SELECT projection van je sql query doen dmb COALESCE(), makkelijker dan op de client, want waarschijnlijk sneller.

Je vermeldt niet of al de restricties die hier vermeldt staan: MSDN: Creating a Query for Notification ook kloppen, bv of je connection deze heeft. Je hebt een left join, maar dat is een outer join, en die mogen niet. LEFT JOIN is eigenlijk LEFT OUTER JOIN maar dat schrijft niemand.

zie ook: http://stackoverflow.com/...itations-of-sqldependency

m.a.w.: als deze query moet worden uitgevoerd wanneer een table wijzigt, is het wellicht beter om een jobqueue te maken waarin je jobs plaatst in de method die de wijzigingen doorvoert op de DB, zodoende heb je geen last van de beperkingen van sql dependencies.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
EfBe schreef op donderdag 01 mei 2014 @ 09:00:
'ik krijg exceptions' maar je vermeldt niet welke, wat het onmogelijk maakt je vraag te beantwoorden.

Je username test kun je ook in de SELECT projection van je sql query doen dmb COALESCE(), makkelijker dan op de client, want waarschijnlijk sneller.

Je vermeldt niet of al de restricties die hier vermeldt staan: MSDN: Creating a Query for Notification ook kloppen, bv of je connection deze heeft. Je hebt een left join, maar dat is een outer join, en die mogen niet. LEFT JOIN is eigenlijk LEFT OUTER JOIN maar dat schrijft niemand.

zie ook: http://stackoverflow.com/...itations-of-sqldependency

m.a.w.: als deze query moet worden uitgevoerd wanneer een table wijzigt, is het wellicht beter om een jobqueue te maken waarin je jobs plaatst in de method die de wijzigingen doorvoert op de DB, zodoende heb je geen last van de beperkingen van sql dependencies.
:F Jeetje, die left join had ik natuurlijk moeten weten dus dat is geen optie.

Mijn kennis laat mij hier en daar in de steek, excuses hiervoor. De SqlNotificationEventArgs geeft dus niet zozeer een exception maar de propertie info geeft als waarde invalid wat dus wil zeggen dat de notification query niet goed is.
Als ik de left join toevoeg zie ik die invalid terug, nu heb ik dit weer aangepast naar mijn vorige situatie en haal ik userid en guestname op. Ik heb ook geprobeerd een scaler valued funtie te gebruiken waar ik userid en guestname instop en vervolgens 1 waarde(username of guestname) return. Ik vermoed alleen dat scaler valued functies niet in de select voor mogen komen want mijn SqlNotificationEventArgs geeft dan weer invalid en ik kan dan volgens mij ook niet voldoen aan de eerste regel in: http://stackoverflow.com/...itations-of-sqldependency
Wat ik nu doe is userid en guestname ophalen, als userid is gevuld dan haal ik, door een aparte query, de username op. Dat werkt alleen is dit dus alles behalve efficiënt.

Ik begin nu de inefficiëntie van mijn opstelling te zien en ben dus aan het twijfelen of dit wel een goede oplossing is. Ben er namelijk achtergekomen dat als mijn notificatie query "geraakt" wordt de hele dataset van die notificatie query door mijn reader gaat en gezien mijn query nu kijkt naar alle berichten van de afgelopen 5 uur kan dit, in de praktijk, een flinke resultset worden. Het probleem is echter dat de tabel waar ik de records uithaal door zowel een webapplicatie als een externe applicatie wordt beïnvloed. Ik kan dus ook geen jobqueue maken omdat de wijzigingen in de database tabel niet alleen door mijn web applicatie worden gedaan. Vandaar dat ik met deze notification query had gehoopt een signaal te kunnen krijgen indien er een wijziging plaats vind.

Iemand een idee hoe ik dit zou kunnen doen?

Dying is God's way of telling you, you've been FIRED.

Pagina: 1