Seite 1 von 2

ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 00:19
von Sten Schmidt
Hallo Zusammen,

ich habe beim Testen ein Probem beim Where mit dem RelationalOperators_Between-Operator:

Code: Alles auswählen

SqlAnweisung = SqlTools.SqlGenerator(SqlTools.SqlConverters.DaoSqlConverter) _
                  .From("Tab1") _
                  .Where("F2", RelationalOperators_Between, 2) _
                  .Select("F1", "F2").SelectField("Count(*)", "", "Anzahl") _
                  .ToString()

=> Select F1, F2, Count(*) As Anzahl From Tab1 Where (F2  2)
 


Der Operator wird im ResultString nicht ausgegeben und es ist aktuell (SVN Rev. 115) wohl nicht möglich einen 2. Parameter anzugeben.

(Schreibe dies hier rein weil das Projekt im Mantis noch nicht eingerichtet ist)

Viele Grüße

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 10:46
von Josef Pötzl
Hallo Sten!

Dir ist aber schon bewusst, dass der SqlGenerator noch nicht fertig ist? :)
Between ist ganz einfach noch gar nicht eingebaut .. muss ja auch nicht nicht, da es keinen Test dafür gibt, der fehl schlägt. :D

mfg
Josef

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 13:23
von Sten Schmidt
Hi Josef,

Josef Pötzl hat geschrieben:Dir ist aber schon bewusst, dass der SqlGenerator noch nicht fertig ist? :)
Between ist ganz einfach noch gar nicht eingebaut ..


war mir schon klar. :)

Ich wollte damit nur indirekt sagen, dass ich hier ein Strukturproblem sehe, wobei ich ehrlich gesagt auch nicht weiß wie man das am besten Lösen kann.

Also wenn ich folgendes Benutze:

Code: Alles auswählen

...
selectQuery.Where("F1", RelationalOperators.Between, 1, 2);
...
 


... und mal angenommen es gäbe schon eine entsprechende Überladug für den zweiten Parameter in:

Code: Alles auswählen

    public interface IFieldCondition : ICondition
    {
        IField Field { get; set; }
        RelationalOperators Operator { get; set; }
        object Value { get; set; }
    }
 


.. dann ist mir noch nicht klar wie man sicherstellen könnte dass der User beim Verwenden des Where-Ausdrucks genau dann wenn der Operator auf "Between" steht auch zum Verwenden der zweiten Überladung gezwungen werden könnte (z.B. durch Kompiler-Fehler).

Oder denke ich zu kompliziert??

Gruß Sten

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 14:00
von FireWalkerHH
Mhh, also wenn schon zur Kompilierzeit ein Fehler auftreten soll, dann müsste man eine zusätzliche Where-Funktion einbauen.

Code: Alles auswählen
selectQuery.WhereBetween("F1", 1, 2);


Und dann könnte man den Operator 'Between' auch weglassen.


Oder es gibt eine Überladung vom 'Where' die als Parameter ein Field, und zwei Values erwartet.

Und das IN fehlt ja auch noch: Da stelle ich mir folgendes vor:
Eine 'Where'-Funktion die ein Field und eine ValueList bekommt und ein 'Where' das ein Field und ein SubSelect bekommt.

Gruß,
Thomas

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 14:02
von Josef Pötzl
Hallo!

In Net brauchen wir keinen 2. Value-Parameter.

Code: Alles auswählen
selectQuery.Where(new Field("F1"), RelationalOperators.Between, New BetweenValue(1, 2));


Das hindert zwar den Nutzer der Lib nicht daran folgendes zu schreiben:
Code: Alles auswählen
selectQuery.Where(new Field("F1"), RelationalOperators.Between, 1);

... aber dann kann man ja eine Exception auslösen. Irgendwann wird er sich das schon merken, dass man für Between 2 Parameter übergeben muss.

Damit man es zum Compiler-Fehler kommt, müsste man eine extra Enum verwenden.
=>
Code: Alles auswählen
public ISqlGenerator Where(IField field, RelationalOperatorsMIt1Value relationalOperator, object value)

und
Code: Alles auswählen
public ISqlGenerator Where(IField field, RelationalOperatorsMit2Values relationalOperator, object value1, object value2)

bzw.
Code: Alles auswählen
public ISqlGenerator Where(IField field, RelationalOperatorsMit2Values relationalOperator, object[2] values)

bzw.
Code: Alles auswählen
public ISqlGenerator Where(IField field, RelationalOperatorsMit2Values relationalOperator, IExtraInterface values)


Ich würde mir das aber für den Anfang nicht antun und auf etwas Mitdenken des Programmiers hoffen. :)


Für VBA würde ich allerdings für die vereinfachte Eingabe eine WhereBetween-Prozedur in der COM-dll gestalten.

mfg
Josef

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 20:26
von Sten Schmidt
Josef Pötzl hat geschrieben:Für VBA würde ich allerdings für die vereinfachte Eingabe eine WhereBetween-Prozedur in der COM-dll gestalten.


Ja, darauf wird es wohl hinauslaufen, wobei sich mir dann die Frage stellt ob man das nich gleich für jeden RelationalOperator macht, weil so ehwig viele Varianten werden dabei ja nicht auftreten.

Vielleicht nur als Idee (Pseudocode):

Code: Alles auswählen


foo.Where.IsNot("F1", 0)
foo.Where.IsEqual("F1", 0)
foo.Where.IsLessThan("F1", 0)
foo.Where.IsGreaterThan("F1", 0)
foo.Where.IsLike("F1", 0)
foo.Where.IsBetween("F1", 0, 9)
foo.Where.IsIn("F1", ???)

 

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 20:32
von Josef Pötzl
Hallo!

Es fehlt noch:
foo.Where.IsEqualOrGreaterThan(...)
foo.Where.IsEqualOrLessThan(...)

+ alle mit Not, wobei man hier eine "WhereNot"-Klasse nutzen könnte:
foo.Where.Not.IsEqual("F1", 0)
foo.Where.Not.IsLessThan("F1", 0)
foo.Where.Not.IsGreaterThan("F1", 0)
foo.Where.Not.IsLike("F1", 0)
foo.Where.Not.IsBetween("F1", 0, 9)
foo.Where.Not.IsIn("F1", ???)
foo.Where.Not.IsEqualOrGreaterThan(...)
foo.Where.Not.IsEqualOrLessThan(...)

Ich finde, dass dann der Code etwas lästiger zu bedienen wird, da man dann nicht mehr "... Where(...).Where(...).Having(..)" schreiben kann.
Andererseits wird er vielleicht sogar (je nach Geschmack) lesbarer.

Einen Nachteil hat so ein Konstrukt aber: sobald man eine Bedingungsart ergänzt, muss man das COM-Interface ändern.
Bei der Variante mit Where(Element, Vergleichsparameter, Vergleichselement) muss man nur den Code dahinter anpassen, kann aber die COM-Schnittstelle unverändert lassen.

In der "reinen" .net-Lib will ich so etwas aber nicht haben, da man dort mit Überladungen arbeiten kann.

Mir selbst gefällt es für VBA so besser:
Code: Alles auswählen
foo.Where(Feld, RelationalOperators_Like, "abc*")


Between könnte ich mir z. B. auch so vorstellen:
Code: Alles auswählen
SqlGenerator.Where(Feld, RelationalOperators_Between, Array(von, bis))

'oder
With SqlGenerator
   .Where(Feld, RelationalOperators_Between, .BetweenParam(von, bis))
end With

'oder
With SqlGenerator
   .Where(.BetweenCondition(Feld, von, bis))
end With


mfg
Josef

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: So 18. Mär 2012, 22:48
von Sten Schmidt
Hoi Zusammen,

habe jetzt mal versucht

Code: Alles auswählen

.WhereBetween("F1", 1, 2)
 


einzubauen, aber ich komme nur bis:

Code: Alles auswählen

Select F1, F2, F3 From TabA Where (F1 Between AccessCodeLib.Data.SqlTools.Sql.BetweenValue) Group By F2 Order By F1
 


Also für die Struktur der Lib braucht man ja ne Landkarte. :)

(Ich hol mir jetzt ein Bier, Feierabend für heute... :D )

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: Mo 19. Mär 2012, 08:20
von Josef Pötzl
Die Landkarte ists verfügbar - du kannst ein Klassendiagramm vom Visual Studio erstellen lassen. :)

Wenn du es dir das Prinzip ansiehst, ist das aber gar nicht so komplex.
Der SqlGenerator ist zum Zusammensetzen der SQL-Elemente. Der Converter konvertiert diese Sammlung in den jeweiligen Dialekt. Da bei Where, Having on On (vom Join) die gleiche Aufgabe mehrmals benötigt wird, übernimmt das ein ConditionConverter, um keinen Code wiederholen zu müssen.

=> Also einen Test für den ConditionConverter schreiben und dann Between dort einbauen.
Ich würde die Libs gerne testgetrieben entwickeln, da wir durch Tests vorab schon zeigen, wie etwas verwendet wird. Außerdem kann es uns dann nicht passieren, dass ein anderer einen Code anpasst und dabei etwas anders (das er vielleicht gar nicht kannte) nicht mehr läuft.

mfg
Josef

Re: ISqlGenerator Where mit RelationalOperators_Between

BeitragVerfasst: Mo 19. Mär 2012, 11:44
von Sten Schmidt
Moin,

Josef Pötzl hat geschrieben:=> Also einen Test für den ConditionConverter schreiben und dann Between dort einbauen.
Ich würde die Libs gerne testgetrieben entwickeln, da wir durch Tests vorab schon zeigen, wie etwas verwendet wird. Außerdem kann es uns dann nicht passieren, dass ein anderer einen Code anpasst und dabei etwas anders (das er vielleicht gar nicht kannte) nicht mehr läuft.


Kann man die Tests aus Visual Studio heraus starten? Dort gibt es ja das Menü "Test", aber das hat nix mit NUnit zu tun.
Bzw. wäre es das "korrekte" Vorgehnen wenn ich die foo.Test.dll per Drag&Drop in das NUnit-Tool ziehe oder geht das auch einfacherer?