Subsonic 2.2 SqlQuery with complicated clauses - c#

I've written the following query for a resource scheduling calendar app. The query is used to find any events already scheduled on the calendar that would conflict with the event of interest:
string qry = "SELECT * FROM " + EventX.Schema.TableName +
" WHERE " +
" ( " +
" ( " +
EventX.Columns.StartTime + " >= '" + startTime +
"' AND " + EventX.Columns.StartTime + " < '" + endTime +
"' ) " +
" OR " +
" ( " +
EventX.Columns.EndTime + " > '" + startTime +
"' AND " + EventX.Columns.EndTime + " <= '" + endTime +
"' ) " +
" ) " +
" AND " +
" ( " +
EventX.Columns.EventID + " <> " + eventId +
" AND " + EventX.Columns.StatusID + " IN " +
" ( " +
(int) EventStatus.Approved + " , " +
(int) EventStatus.Completed +
" ) " +
" ) ";
QueryCommand qc = new QueryCommand(qry, EventX.Schema.Provider.Name);
EventXCollection events = new EventXCollection();
events.LoadAndCloseReader(DataService.GetReader(qc));
The above query works, but it's a freakishly ugly abomination in terms of aesthetics and I'd prefer not to leave a mess for whoever has to maintain this after me. I wrote this query after having tried and failed to get it working using a SqlQuery instead. The closest I came to getting it right before giving up on SqlQuery and writing the functional-but-ugly hack above was the following (incorrect) query:
SqlQuery qry = new Select().From(EventX.Schema.TableName);
qry.WhereExpression(EventX.Columns.StartTime).IsGreaterThan(startTime);
qry.And(EventX.Columns.StartTime).IsLessThan(endTime);
qry.OrExpression(EventX.Columns.EndTime).IsGreaterThan(startTime);
qry.And(EventX.Columns.EndTime).IsLessThan(endTime);
qry.AndExpression(EventX.Columns.EventID).IsNotEqualTo(eventId);
qry.And(EventX.Columns.StatusID).In((int)EventStatus.Approved, (int)EventStatus.Completed);
I'm working on maintaining an application written by a developer who has since moved on and this is my first experience working with Subsonic. Note that if event A ends at 2:00 PM and event B starts at 2:00 PM, then events A and B do not constitute a scheduling conflict and the query should reflect that. How would you write this query using Subsonic?

If i'm correct, EventX.Schema.TableName and EventX.Columns.xyz are just constants, and actual variables are startTime, endTime and eventId right?
If so, why not make a stored proc, or at least a parameterized query, so SQL can cache execution plans? IIRC Subsonic supports SPs, but the project site looks like it's about to fall apart.
Sql something like this, could be an SP, or a parameterized query:
SELECT * FROM EventTable
WHERE
(
(
StartTime >= #startTime
AND StartTime < #endTime
)
OR
(
EndTime > #startTime
AND EndTime <= #endTime
)
)
AND
(
EventID <> #eventId
AND
StatusID IN ( 1,2 )
--just made up these numbers, should be the ID of Approved and Completed ...
)
And pass in #startTime, #endTime and #eventId as parameters?
Although I don't know the state of you project, but if I was in your place, probably I would try to leave what's working correctly as it is. And slowly try to replace Subsonic with something actively used in the world, or you are experienced in using it. Would be better both for you, and whoever will have to maintain it later.
Subsonic 3.0 was released about two ago, and feels pretty much dead now. Rob Connery created Massive since, and pretty much abandoned Subsonic if I'm correct...
Edit
Just to make it clear: I'm not saying Subsonic is bad, used and tweaked it's T4 templates a lot to suit my needs. About 2 years ago. But not a lot of people are familiar with it, so moved to other, more widely known data access techniques...

Related

Why does sqlite converts . To ,

I am completely confused by SQLite right now.
I use the System.Data.SQLite Version for C#
I have two Tables:
Table 1:
In it I have created two columns (more but they are the important in this case and the statement is way to long to post it). The first one is called RecStat and the second one DOXinM.
Both are a Decimal and are created like this:
...
[RectStat] Decimal,
[DOXinM] Decimal,
...
The Create Table statement looks like this:
Create Table If Not Exists "Table1"
(..Columns..);
When I insert a value in this table the decimal works perfectly fine and when I read it out it works too on the xaml GUI.
After that I created a second Table which also has a Decimal Column.
I Created the table the same way (this is a short one, So i can give the whole statement)
Create Table If Not Exists "Table2" (
[ID] Integer Not Null Primary Key,
[Material] VarChar(10],
[Thickness] Decimal);
C# Code for the creation (Note that I work with a const string for all SQL Commands):
mySQLiteCommand.CommandText = #"" + DatabasePara.CREATE_SQL + " " + DatabasePara.TABLE_SQL + " " + DatabasePara.IF_SQL + " " + DatabasePara.NOT_SQL + " " + DatabasePara.EXISTS_SQL + " " + DBTableFilter.Filter + "
mySQLiteCommand.CommandText += #"([" + DBTableFilter.ID + "] " + DatabasePara.INTEGER_SQL + " " + DatabasePara.NOT_SQL + " " + DatabasePara.NULL_SQL + " " + DatabasePara.PRIMARYKEY_SQL + ", ";
mySQLiteCommand.CommandText += #"[" + DBTableFilter.Material + "] " + DatabasePara.VARCHAR_SQL + "(360), ";
mySQLiteCommand.CommandText += #"[" + DBTableFilter.Thickness + "] " + DatabasePara.DECIMAL_SQL + ");";
mySQLiteCommand.ExecuteNonQuery();
In both case I do the same insert for the Decimal Column:
Insert into Table1 ('RectStat') values ('10.5');
Insert into Table1 ('DOXinM') values ('1.3');
Insert into Table2 ('Thickness') values ('0.25');
For the Table2 Insert:
for (int FilterIndex = 0; FilterIndex < Database.FilterTable.FilterList.Count; FilterIndex++)
{
mySQLiteCommand.CommandText = #"" + DatabasePara.INSERTINTO_SQL + " " + DBTableFilter.Filter + "(" + DBTableFilter.Material + ", " + DBTableFilter.Thickness + ") ";
mySQLiteCommand.CommandText += #"" + DatabasePara.VALUES_SQL + " ('" + Database.FilterTable.GetFilterAt(FilterIndex).Material_Property + "', " + Database.FilterTable.GetFilterAt(FilterIndex).Thickness_Property + ");";
mySQLiteCommand.ExecuteNonQuery();
}
Now the Database inserts the first two Statements as 10.5/1.3 and the last one as 0,25
When I read out the value the first two works perfectly fine but the last one is shown without the numbers after the decimal "point".
So my question is.
Why does this happens?
(Btw I have more than 20 Decimals columns in my table and the "Thickness" is the only one with this problem)
I hope you can help me.
Thanks in Advance
Richard
What I have tried:
Tried different Values (Had the hope that it was because of the 0.25)
Tried it without the ''. But than the statement thought it had three values for two columns...
First of all, you should use parameterized queries. They will get rid of conversion problems and prevent sql injection. Most likely your issues are created by the fact, that your type of query creation calls decimal.ToString() implicitly. For certain locales, this replaces the . with a , which leads to a syntax error.
var query = "INSERT INTO yourtable COLUMNS(col1, col2, col3) VALUES(#p1, #p2, #p3)";
var cmd = new SQLiteCommand(query, connection);
cmd.Parameters.AddWithValue("#p1", 1);
cmd.Parameters.AddWithValue("#p2", 2.2);
cmd.Parameters.AddWithValue("#p3", "three");
cmd.ExecuteNonQuery();
This will, among other things, send the decimals to your server in a correct format, and also take care of possible ' quotes in your string literals and prevent sql injection, thus making your code more secure.

ORA-01036 after rewriting an Oracle insert command

I am reworking legacy code and came to this query:
sqlDS.InsertCommand = "INSERT INTO SCHEMA.TABLE " +
"(ID, DATUM, ID_STATE, G_AM, G_VON, DATUM_BEW) " +
"VALUES (" + ((strukturen.Login)Session["svar_bew"]).ID_Bew.ToString() +
", TO_DATE('" + _datum + "', 'DD.MM.YYYY HH24:MI:SS'), 2, TO_DATE('" + lbl_bew.Text +
"', 'DD.MM.YYYY'), 'ID" + ((strukturen.Login)Session["svar_bew"]).ID_Bew.ToString() +
"', TO_DATE('" + _datum + "', 'DD.MM.YYYY HH24:MI:SS'))";
Which works, but I want this abomination rewritten into a paramerterized format, for obious reasons.
Now this is my progress so far:
sqlDS.InsertCommand = "INSERT INTO SCHEMA.TABLE (ID, DATUM, ID_STATE, G_AM, G_VON, DATUM_BEW) " +
"VALUES (:Id_Bew, TO_DATE(':Datum', 'DD.MM.YYYY HH24:MI:SS'), 2, TO_DATE(':BewAm', 'DD.MM.YYYY'), 'ID' || :Id_Bew, TO_DATE(':Datum', 'DD.MM.YYYY HH24:MI:SS'))";
sqlDS.InsertParameters.Add("Id_Bew", ((strukturen.Login)Session["svar_bew"]).ID_Bew.ToString());
sqlDS.InsertParameters.Add("Datum", _datum);
sqlDS.InsertParameters.Add("BewAm", lbl_bew.Text);
This is the table in question:
COLUMN | TYPE
-----------------------
ID | NUMBER
DATUM | DATE
/* Columns | ommited */
ID_STATE | NUMBER
G_AM | DATE
G_VON | CHAR(10 BYTE)
DATUM_BEW | DATE
The variables follow no fixed schema yet, so they were declared in German, never mind that in this case.
The problem is, that this new code now throws an ORA-01036 an I suspect that it is at this location:
'ID" + ((strukturen.Login)Session["svar_bew"]).ID_Bew.ToString() --> 'ID' || :Id_Bew
In the original SQL query the string "ID" is concatinated with an numeric ID which is pulled out of a session variable. My suspicion is, that I concatinated it the wrong way in my paramerterized query and botched up the syntax.
Question is: How can I resolve this error and bring this insert command into a proper format?
Bind Variables Should be defined without embedding in single quotes.
':bind_variable' ---> Wrong (Treated as plain string instead)
:bind_variable ---> Right
So, When you attempted to add a bind parameter, it threw ORA-01036: illegal variable name/number
sqlDS.InsertCommand = "INSERT INTO SCHEMA.TABLE (ID, DATUM, ID_STATE, G_AM, G_VON, DATUM_BEW) " +
"VALUES (:Id_Bew, TO_DATE(:Datum, 'DD.MM.YYYY HH24:MI:SS'), 2, TO_DATE(:BewAm, 'DD.MM.YYYY'), 'ID' || :Id_Bew, TO_DATE(:Datum, 'DD.MM.YYYY HH24:MI:SS'))";
sqlDS.InsertParameters.Add("Id_Bew", ((strukturen.Login)Session["svar_bew"]).ID_Bew.ToString());
sqlDS.InsertParameters.Add("Datum", _datum);
sqlDS.InsertParameters.Add("BewAm", lbl_bew.Text);

MySQL leading whitespace with C#

When I update a field in my MySQL database, it always adds a whitespace to the value.
I tried to remove the whitespace with the trim-command and the replace-command. Neither of them worked. So I expect that it isn't a whitespace but some vague ASCII character. These are the commands I used:
this.foo = result.GetValue(0).ToString().Trim();
this.bar = result.GetValue(0).ToString().Replace(" ","");
The field it updates is a VARCHAR(xx). This is my MySQL update command:
MySqlCommand cmd = new MySqlCommand("UPDATE " + table + " SET " + new_field + " =' " + new_value+ "' WHERE " + field+ "= " + value + "",this.con);
this.con is my connection to the MySQL database.
FYI: I use .NET 3.5CF with a mysql.data.cf DLL in Visual Studio 2008.
Could someone help me out with this problem? It's driving me nuts.
Well yes, you've got a leading space in the SQL:
"UPDATE " + table + " SET " + new_field + " =' " + new_value+ "'
Note the bit straight after "=" - you've got a quote, then a space, then new_value.
However, you shouldn't be putting the values in the SQL directly in the first place - you should be using parameterized SQL statements... currently you've got a SQL injection attack waiting to happen, as well as potential problems for honest values with quotes in.
You should use parameterized SQL for both new_value and value here... I'm assuming that field and table come from more "trusted" sources?
This appears to have a space where the * is
" ='*" + new_value

windows service exception in .NET

I will be tested the application as windows application then it will be stored the datetime in MySQL data base.When I will be start this application using windows service it will be thrown this exception.
error [HY000][MySQL][ODBC 3.51 Driver] [MySqlid -6.0.11-alpha-community]incorrect datetime value " 5/6/2011 9:00:00 AM" for column column-name at row1
Windows application take the system format & my system format is yyyy-MM-dd hh:mm:ss
in windows service which format is used.
query18 += "select '" + obj8 + "' as DTvalue ,'" + date8 + "' as DTdatelogged1 ,'" + OpcGroup.QualityToString(e8.sts[counter8].Quality) + "' as DTquality ,'" + DateTime.FromFileTime(e8.sts[counter8].TimeStamp) + "' as DTtimestamp ,'" + e8.sts[counter8].HandleClient + "' as DTparamID Union " + Environment.NewLine;
UpdateQuery = Update parameter t Left join + Environment.NewLine;
UpdateQuery8 += ( + query18 + ) Temp on" + Environment.NewLine;
UpdateQuery8 += t.itemID=Temp.DTparamID+ Environment.NewLine;
UpdateQuery8 += set paramvalue=DTvalue, date_logged1=DTdatelogged1,Quality= DTquality,date_logged=DTtimestamp + Environment.NewLine;
UpdateQuery8 += where t.groupID=9 and t.itemID=Temp.DTparamID;
my query likethis timestamp value is 129500892576718750 it will be convert DateTime.FromFileTime() function converted value like '2011-05-17 12:30:57' in windows application it will be write into mysql database
but in windows service converted value like 2011/05/17 12:30:57 PM it will be not accepted by the MYSQL database same thing i will be used in the windows service
now
UpdateQuery8 = "Update parameter " + Environment.NewLine;
UpdateQuery8 += "set paramvalue=#paramvalue,date_logged1=#date_logged1,Quality=#Quality,date_logged=#date_logged" + Environment.NewLine;
UpdateQuery8 += "where groupID=9 and itemID=#itemID";
cmd8 = new OdbcCommand(UpdateQuery8, con136);
cmd8.Parameters.Add("#paramvalue", obj8.ToString());
cmd8.Parameters.Add("#date_logged1", date8);
cmd8.Parameters.Add("#Quality", OpcGroup.QualityToString(e8.sts[counter8].Quality));
cmd8.Parameters.Add("#date_logged", dt);
cmd8.Parameters.Add("#itemID",e8.sts[counter8].HandleClient);
cmd8.ExecuteNonQuery();
it will be execute but there no updation in database
Please help me in this regard.
Thanks in Advance.
Always use parametrized queries to pass data to the DB driver. Then it is up to the driver to format your dates correctly, and you avoid being susceptible to SQL-Injection attacks.
Create a datetime and format it the way YOU want. Not the system defaults, not the casual user defaults, the one you want.
DateTime dt = DateTime.Now;
String str = dt.ToString("yyyyMMdd");
This should lead to "20110517" if i'm not mistaking.
Bonus points are given if you use one of the better answers setting the code locale to the one used by the mysql server. But the one above should give you a way that works.

MS Access statement for selecting data within selected date

I need a statement to select data from an MS Access database table.
WITHIN selected dates
I have two textboxes in my GUI called StartDate and EndDate
I want to select data within those 2 dates.
I have tried 2 methods.
The first is
" DAY(V.RegDate) between " + Start.ToString("dd")
+ " and " + End.ToString("dd");
" and MONTH(V.RegDate) between " + Start.ToString("MM") + " and "
+ End.ToString("MM");
" and YEAR(V.RegDate) between " + Start.ToString("yyyy") + " and "
+ End.ToString("yyyy");
V.RegDate is the date column from the database.
But it returns me no data when I select 01/08/2010 and 01/09/2010 while there is some data at 25/08/2010.
I think that is because I chose the date separately and since the 2 dates are the same,
returns me nothing
I have tried another way...
" V.RegDate between #" + Start.ToString("dd/MM/yyyy") + "# and #" _
+ End.ToString("dd/MM/yyyy") + "#";
This also return me nothing
Any Ideas????
This pattern works for me:
SELECT sometable.somedate
FROM sometable
WHERE (((sometable.somedate) Between #2/1/2010# And #4/1/2010#));
(in this case it's MDY, I normally prefer ISO-ish style - YYYY/MM/DD because there is no way that Access can screw that up)
Maybe you've got your date set using the American default - MDY instead of the British(?) standard DMY.

Categories