[LINQ 2 SQL] Query compiling in entities

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
Ik heb het volgende stuk code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        public List<Day> GetDays(int month, int year)
        {
            int daysInMonth = DateTime.DaysInMonth(year, month);

            DateTime min = new DateTime(year, month, 1);
            DateTime max = new DateTime(year, month, daysInMonth);

            //we cast to List so that it executes the query.
            //having it just in an IEnumerable doesn't do that
            //and then you get ~30+ calls in the next for block to the db
            return daysThatHaveData = (from
                                            day in this.Days
                                          where
                                            //not neccesary since we already are IN a user
                                            //day.UserID == this.UserID &&
                                            day.Date >= min &&
                                            day.Date <= max
                                          select
                                            day).ToList<Day>();
        }

Dit stuk code wordt in een User (ook een entity uit de database) uitgevoerd.

Een user heeft een reeks aan dagen in een Days tabel, vandaar dat ik zoek in this.Days :)

Dus de call gaat als volgt:
C#:
1
2
3
4
5
6
7
User user = context.Users.SingleOrDefault(u => u.UserID == 1);
if(null != user)
{
   var list = user.GetDays(1, 2008);
   //doe iets met list
}
//...


Het gekke is dat de query die wordt uitgevoerd door LINQ de volgende is:
SQL:
1
2
3
4
5
SELECT [t0].[DayID], [t0].[Date], [t0].[WorkedHours], [t0].[UserID], [t0].[PeriodID], [t0].[Comment], [t0].[VacationHours], [t0].[SickHours]
FROM [dbo].[Days] AS [t0]
WHERE [t0].[UserID] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926

Probleem: waarom neemt hij m'n Date niet mee?

In eerste instantie dacht ik dat hij het niet kreeg omgezet naar een db type dus ik ging hier zoeken:
http://msdn.microsoft.com/en-us/library/bb882657.aspx

Maar alles wat ik gebruik is ervoor bekend, dus alleen groter/gelijk en kleiner/gelijk worden gebruikt in mijn statement.

Dan ging ik verder zoeken, ik voerde de volgende code uit op de context zelf (dus niet in een userentity maar erbuiten):

C#:
1
2
3
4
5
6
7
8
9
10
            DateTime min = new DateTime(2009, 1, 1);
            DateTime max = new DateTime(2009, 1, 30);

            List<Day> list = (from day in this.TimesheetModelDataContext.Days
                       where
                        day.UserID == this._user.UserID &&
                         day.Date >= min &&
                         day.Date <= max
                       select
                         day).ToList<Day>();

En dit geeft de volgende SQL:
SQL:
1
2
3
4
5
6
SELECT [t0].[DayID], [t0].[Date], [t0].[WorkedHours], [t0].[UserID], [t0].[PeriodID], [t0].[Comment], [t0].[VacationHours], [t0].[SickHours]
FROM [dbo].[Days] AS [t0]
WHERE ([t0].[UserID] = @p0) AND ([t0].[Date] >= @p1) AND ([t0].[Date] <= @p2)
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- @p1: Input Date (Size = 0; Prec = 0; Scale = 0) [1/1/2009 12:00:00 AM]
-- @p2: Input Date (Size = 0; Prec = 0; Scale = 0) [1/30/2009 12:00:00 AM]


Waaraan heb ik dit gedrag te danken?

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 00:41

TeeDee

CQB 241

Zijn dit tikfouten:
[code=c#]public List<Day> GetDays(int month, int year) [/code]
en
[code=c#]var list = user.GetDays(2008, 1); [/code]
Dus: 2008 en 1 omdraaien?

Bollocks, DaysInMonth gooit dan een prachtige error :)

[ Voor 16% gewijzigd door TeeDee op 13-10-2009 15:22 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
TeeDee schreef op dinsdag 13 oktober 2009 @ 15:15:
Zijn dit tikfouten:
C#:
1
public List<Day> GetDays(int month, int year) 

en
C#:
1
var list = user.GetDays(2008, 1); 

Dus: 2008 en 1 omdraaien?
Neen dat was een typo :)

Kan ik niet meer diagnostics opvragen van een LINQ query buiten datacontext.Log in te stellen?

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 00:41

TeeDee

CQB 241

this.Days heeft ook values?

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
Yes, de query geeft ook aan beide kanten dezelfde values terug he!

Maar bij de eerste (in de user) doet ie de date vergelijking in .NET en bij de tweede in de SQL query.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Skinny
  • Registratie: Januari 2000
  • Laatst online: 11-09 16:00

Skinny

DIRECT!

De query die je gebruikt van binnenin je 'User' doet een Linq query op this.Days. Dit is een EntitySet in je User object. Aangezien die (nog) niet geladen is wordt blijkbaar eerst de gehele EntitySet eerst geladen voordat de rest van je expressie (het filteren op datum) wordt uitgevoerd.

Ik lees nu hier (als ik het goed interpreteer) :

http://oakleafblog.blogsp...g-depth-and-order-of.html

Dat het dus inderdaad zo is dat voordat je de EntitySet kan filteren, deze eerst 'ordered' moet zijn en dus geladen moet worden?

Nog iemand met dezelfde problematiek..

http://stackoverflow.com/...-subset-of-an-association


(ook zelf weer wat geleerd nu :))

SIZE does matter.
"You're go at throttle up!"


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
Bummer. Dit is echt jammer. Dan maar die functie in m'n context plaatsen. Dan gaat dat wel, en dan geef ik gewoon het id mee.

Voor de anderen die hier komen:

Het probleem zit 'm in het feit dat this.Days (in het eerste blok) een EntitySet<T> is, en die implementeert geen IEqueryable<T> :(

En die van de context is een Linq.Table<T> (en die implementeert natuurlijk wel die IEqueryable<T>

[ Voor 87% gewijzigd door Snake op 13-10-2009 17:00 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

Verwijderd

Kan 't niet aan iets heel simpels liggen, bv. dat LINQ niet blij is met 'min' en 'max' als variabelen?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:22
Skinny schreef op dinsdag 13 oktober 2009 @ 15:42:
De query die je gebruikt van binnenin je 'User' doet een Linq query op this.Days. Dit is een EntitySet in je User object. Aangezien die (nog) niet geladen is wordt blijkbaar eerst de gehele EntitySet eerst geladen voordat de rest van je expressie (het filteren op datum) wordt uitgevoerd.

Ik lees nu hier (als ik het goed interpreteer) :

http://oakleafblog.blogsp...g-depth-and-order-of.html

Dat het dus inderdaad zo is dat voordat je de EntitySet kan filteren, deze eerst 'ordered' moet zijn en dus geladen moet worden?

Nog iemand met dezelfde problematiek..

http://stackoverflow.com/...-subset-of-an-association


(ook zelf weer wat geleerd nu :))
Dit is gewoon logisch.
Die volledige 'Days' set hoort tot de user entity, vandaar dat deze dus als een geheel nog moet geladen worden.

Als ik het zo zie, is de 'Days' property een collectie die lazy geladen wordt. Echter, als je dit doet:
code:
1
from day in this.Days where ..... select day;

dan vind ik het logisch dat het EF eerst de gehele Days collectie gaat gaan ophalen (vandaar die query). Als hij enkel de dagen ophaalt die voldoen aan je selectie criteria, dan is je entity niet compleet geladen ... Dat kan dan best wat problemen geven als je iets zou wijzigen, en opnieuw moet opslaan enz.

Echter, het is toch wel zo dat EF dan uiteindelijk je Days collectie gaat gaan query-en met de criteria die je gegeven hebt ?


Als je dit gedrag niet wilt, dan zou je deze method in een repository of in een service moeten zetten, en niet zozeer in je entiteit.

[ Voor 4% gewijzigd door whoami op 13-10-2009 22:25 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
(ik heb een titlechange aangevraagd om [LINQ] te wijzigen in [LINQ 2 SQL]).

Het gaat dus om het LINQ 2 SQL Framework niet het EF. (EF ondersteunt geen SingeOrDefault bvb).

Vroeger implementeerde EntitySet<T> WEL IQueryable. Nu niet meer.

En hier staat in uitgelegd waarom: http://social.msdn.micros...40-49e0-b715-75a5bd0063dc

Maar zowiezo ben ik even aan het kijken om van LINQ 2 SQL naar EF te gaan. Alleen is de logging in EF veel slechter, ik kan niet zomaar de query opvragen. En EF is nog niet mature genoeg imo.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:22
Snake schreef op dinsdag 13 oktober 2009 @ 23:23:
(ik heb een titlechange aangevraagd om [LINQ] te wijzigen in [LINQ 2 SQL]).

Het gaat dus om het LINQ 2 SQL Framework niet het EF. (EF ondersteunt geen SingeOrDefault bvb).
Dat maakt volgens mij niet uit. Het is gewoon zo dat je je collectie compleet wil hebben.
Stel dat je die 'Dagen' collectie in jouw geval slechts gedeeltelijk ophaalt. (Bv, zoals jij doet, enkel de dagen die in een bepaalde periode vallen).
Stel dat je dan een dag toevoegt, of een dag uit die collectie verwijderd, en je de wijzigingen wil gaan bewaren. Wat moet er dan gebeuren ? Je collectie is niet volledig, maar dat weet je persistence framework niet ... Wat moet er gebeuren met de dagen die niet in de collectie zitten, maar wel in de DB ? Moeten ze verwijderd worden ?
Maar zowiezo ben ik even aan het kijken om van LINQ 2 SQL naar EF te gaan. Alleen is de logging in EF veel slechter, ik kan niet zomaar de query opvragen. En EF is nog niet mature genoeg imo.
Kijk dan eens naar NHibernate.

[ Voor 29% gewijzigd door whoami op 14-10-2009 09:32 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
whoami schreef op woensdag 14 oktober 2009 @ 09:30:
[...]
Dat maakt volgens mij niet uit. Het is gewoon zo dat je je collectie compleet wil hebben.
Stel dat je die 'Dagen' collectie in jouw geval slechts gedeeltelijk ophaalt. (Bv, zoals jij doet, enkel de dagen die in een bepaalde periode vallen).
Stel dat je dan een dag toevoegt, of een dag uit die collectie verwijderd, en je de wijzigingen wil gaan bewaren. Wat moet er dan gebeuren ? Je collectie is niet volledig, maar dat weet je persistence framework niet ... Wat moet er gebeuren met de dagen die niet in de collectie zitten, maar wel in de DB ? Moeten ze verwijderd worden ?
Inderdaad, maar dat wist ik toen nog niet :+
[...]
Kijk dan eens naar NHibernate.
Ja heb ik ook al van gehoord, eens zien of dat ook werkt met LINQ.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:22
Snake schreef op woensdag 14 oktober 2009 @ 09:39:
[...]
Inderdaad, maar dat wist ik toen nog niet :+

[...]
Ja heb ik ook al van gehoord, eens zien of dat ook werkt met LINQ.
Er bestaat Linq to NHibernate, maar dat is waarschijnlijk ook nog niet echt mature.
(Maar, verwacht ook niet het resultaat dat je hier verwachtte. :) Ook hier zal NHibernate de volledige collectie gaan ophalen).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
whoami schreef op woensdag 14 oktober 2009 @ 09:46:
[...]

Er bestaat Linq to NHibernate, maar dat is waarschijnlijk ook nog niet echt mature.
(Maar, verwacht ook niet het resultaat dat je hier verwachtte. :) Ook hier zal NHibernate de volledige collectie gaan ophalen).
Dan is het niet de moeite dat ik naar NHibernate ga. LINQ 2 SQL voldoet dus.

Nuja, 700 records ophalen is nu ook niet ZO veel. (1 record / dag / user), dus voor 365 records / dag.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:22
Tja, ik denk dat je hier gewoon een denkfout doet. Ieder dergelijk framework zal zo te werk gaan.
En ik denk ook dat je hier gewoon een verkeerde (design) keuze maakt.... Is het nodig dat de 'Days' collectie een member is van User ?
Is het niet gewoon beter om je repository uit te breiden met een method ala 'GetActiveDaysForUserInPeriod', die gewoon het gevraagde aantal dagen returned ?
Wat is de reden waarom Days een member is van Person ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
whoami schreef op woensdag 14 oktober 2009 @ 10:12:
Tja, ik denk dat je hier gewoon een denkfout doet. Ieder dergelijk framework zal zo te werk gaan.
En ik denk ook dat je hier gewoon een verkeerde (design) keuze maakt.... Is het nodig dat de 'Days' collectie een member is van User ?
Is het niet gewoon beter om je repository uit te breiden met een method ala 'GetActiveDaysForUserInPeriod', die gewoon het gevraagde aantal dagen returned ?
Wat is de reden waarom Days een member is van Person ?
Zo heeft LINQ 2 SQL mijn Model opgebouwd. Dat is via een foreign key.

Maar ik had het op de User gezet omdat imo dat behoorde tot het domein van de user en niet dat van de datacontext.

Maar inderdaad, als ik het in de datacontext zet heb ik dat probleem niet :)

Wat ik me afvraag: is het fout wat ik doe? Druist dat in tegen Domain Driven Development?

[ Voor 5% gewijzigd door Snake op 14-10-2009 10:30 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:22
Hoe bedoel je 'het domein van de datacontext' ? De datacontext behoort niet tot je (probleem)domein / business model.
Datacontext is een stukje infrastructuur dat je nodig hebt om met de DB te communiceren. (Ik vermoed dat DataContext te vergelijken is met ISession in NHibernate; het Session object geef ik iedere keer door aan mijn repository).

En wat is 'fout'. In termen van DDD probeer je je domein zo te modelleren dat het zo dicht mogelijk bij 'de echte wereld' aanleunt. Je domeinmodel is dan een goede voorstelling van het real life probleem domein.
Echter, natuurlijk zal je daar ook een aantal toegevingen moeten voor doen, omdat het nu eenmaal onmogelijk is om dit op een zo puur mogelijke OO manier voor te stellen.
(Nu, zowiezo vind ik het geen goed idee dat een tool je class-model opbouwt).

In dit geval denk ik dat je je moet afvragen: is het nodig dat mijn Person entiteit iedere keer die Days collectie meezeult.

https://fgheysels.github.io/

Pagina: 1