I am running a SQL query on SQL Server inside of my WPF C# application. The query returns a string which contains the value called MYCOUNT that I want to return to GetNumber. How do I return the value MYCOUNT only to get number and not the entire string?
public string GetNumber(string SkillNumber)
{
DateTime dte = DateTime.Today;
string fixedStartDate = String.Format("{0:yyyy-MM-dd " + "05:00:00.000" + "}", dte);
string fixedEndDate = String.Format("{0:yyyy-MM-dd " + "05:00:00.000" + "}", dte.AddDays(1));
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(SQLHelper.CnnCal("OADB")))
{
var x = connection.Query($"SELECT COUNT(SOURCEID) AS 'MYCOUNT' "
+ "FROM [OADB].[oadb].[CmsCallHistory] "
+ "WHERE disposition = 2 and DISPSPLIT in (" + SkillNumber + ") AND SEGSTOP BETWEEN '" +
fixedStartDate + "' and '" + fixedEndDate + "'");
return x.ToString();
}
}
This is what returns. I only need to return the value:
You get an error because the Dapper Query method returns an IEnumerable, not a single value (indeed you can see that you have one object (an int) in the IEnumerable returned and this object has the value '767')
In Dapper you can use ExecuteScalar to get a single scalar value as your query returns
var x = connection.ExecuteScalar<int>(.....)
You can also still use the Query method but with a Linq twist
var x = connection.Query(.....).Single();
The usual warning about Sql Injection applies to your code albeit parameterize an IN clause is not so simple. And the two dates should be definitively parameters to avoid parsing incompatibilities between what you consider to be a date and what instead the sql server and its locale thinks about transforming a string to a datetime.
Your answer is in the msdn documentation:
https://msdn.microsoft.com/en-us/library/system.data.idbconnection(v=vs.110).aspx
You can try using
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(SQLHelper.CnnCal("OADB")))
{
IDbCommand command = connection.createCommand();
command.CommandText = $"SELECT COUNT(SOURCEID) AS 'MYCOUNT' "
+ "FROM [OADB].[oadb].[CmsCallHistory] "
+ "WHERE disposition = 2 and DISPSPLIT in (" + SkillNumber + ") AND SEGSTOP BETWEEN '" +
fixedStartDate + "' and '" + fixedEndDate + "'";
return (string)command.ExecuteScalar();
}
Another note: You want to try and close the connection once you are done. I recommend putting this in a try/catch/finally statement so you can close your connection in the 'finally' section.
Hope this helps!
Related
OK so I am using MVS 2015 to right a database using windows Forms and C#
This is what I coded
internal static decimal getExpenseSum(int parsedProjectID, string type)
{
decimal value = decimal.Zero;
string query = "SELECT sum(TotalReceiptAmount) " +
"FROM Expense WHERE ProjectID = " +
parsedProjectID + " AND Type = " + type;
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
value = Convert.ToDecimal(cmd.ExecuteScalar());
conn.Close();
return value;
}
And I am getting a exception stating that the column name 'Parts' is not a valid column name. when "Parts" is the type string sent to the function.
type is varchar/string type, surround it with quotes:
string query = "SELECT sum(TotalReceiptAmount) " +
"FROM Expense WHERE ProjectID = " +
parsedProjectID + " AND Type = '" + type + "'";
^____________^
For better readability do this for your varchar/string types:
type = "'" + type + "'";
string query = "SELECT sum(TotalReceiptAmount) " +
"FROM Expense WHERE ProjectID = " +
parsedProjectID + " AND Type = " + type ;
It seems like the string that you send to function - 'Parts' should be in quotes when you compare for e.g. the resulting query from your code should be :
SELECT sum(TotalReceiptAmount) FROM Expense WHERE ProjectID = parsedProjectID AND Type = 'Parts';
You need to quote your type parameter, otherwise it will be interpreted as a column name instead of a value:
string query = "SELECT SUM(TotalReceiptAmount) " +
"FROM Expense WHERE ProjectID = " +
parsedProjectID + " AND Type = '" + type + "'";
^ ^
Better yet is to use prepared statements to
handle parameter types automatically;
safeguard your code against sql injections;
optimize query execution.
New error Object cannot be cast from DBNull to other types.
using
internal static decimal getExpenseSum(int parsedProjectID, string type)
{
decimal value = decimal.Zero;
type = "'" + type + "'";
string query = "SELECT sum(TotalReceiptAmount) " +
"FROM Expense WHERE ProjectID = " +
parsedProjectID + " AND Type = " + type;
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
value = Convert.ToDecimal(cmd.ExecuteScalar());
conn.Close();
return value;
}
OK so that worked but I am doing it three times for ""Parts"" ""Tools"" and """other"" and of course Ive just only entered one for parts and then the form goes back to the project form and tries to do theese sums and there is nulls for Tools and Other. so Ill have to do a try catch.....
but thank you all for the solve....
That is the meat of my project if you will workflow add customer....
Now on to adding projects to existing customers and then reports. YEAH and once again thank you
am writing a c# code in which am trying to update 4 of the 10 columns of the table. Here is my function type in which am sending arguments for the query:
public int checkout_visitor(int check_inn, int checkout, String time_out, String date_out, String cnic)
Now what happens is that i call this function somewhere in my program providing values in argument:
checkout_visitor(chk_in,chk_out,t_out,dt_out,idcardnum);
The query am using to update my columns is given by:
String query2 = " UPDATE visit_detail SET[check_in] = " + check_inn + "[check_out] = " + checkout + "[time_out] = " + time_out + "[date_out] =" + date_out + "where visit_detail.v_id = "+ v_idd;
Given me exception incorrect syntax near chkout. Where am i wrong?? is the syntax correct? how do i correct it?
code:
public int checkout_visitor(int check_inn, int checkout, String time_out, String date_out, String cnic)
{
try
{
connection.Open();
String query = "select v_id from visitor where visitor.cnic=" + cnic;
command = connection.CreateCommand();
command.CommandText = query;
visitor_id = command.ExecuteScalar().ToString();
int v_idd = Int32.Parse(visitor_id);
String query2 = " UPDATE visit_detail SET[check_in] = " + check_inn + "[check_out] = " + checkout + "[time_out] = " + time_out + "[date_out] =" + date_out + "where visit_detail.v_id = " + v_idd;
//String query2 = "UPDATE visit_detail SET [check_in] = " + check_inn + ",[check_out] = " + checkout + ",[time_out] = " + time_out + ",[date_out] =" + date_out + " where visit_detail.v_id = " + v_idd;
command = connection.CreateCommand();
command.CommandText = query2;
int result = command.ExecuteNonQuery();
connection.Close();
return result;
}
catch (Exception e)
{
return -1;
}
}
Problem :
1.you are not seperating the Parameters properly using comma , .
2.you are not giving the sapace between SET and check_in parameter.
Try This:
String query2 = "UPDATE visit_detail SET [check_in] = " + check_inn + ",[check_out] = " + checkout + ",[time_out] = '" + time_out + "',[date_out] ='" + date_out + "' where visit_detail.v_id = "+ v_idd;
Do you see the resulting query? It seems to me you're missing some comma, but you should print (and post) the resulting query to have a better understanding of the issue.
You are missing ',' between the column names.
Its like Update Table Set col1=3,col2='test'
The problem is that query2 string will be something along the lines:
UPDATE visit_detail SET[check_in] = " 1[check_out] = 2[time_out] = some time[date_out] =some datewhere visit_detail.v_id = 5
So you can already see that there's datewhere that is incorect, there are also no ' characters around string parameters, and no commas between parameters.
Quick fix to that would be:
String query2 = String.Format("UPDATE visit_detail SET [check_in]={0}, [check_out]={1}, [time_out]='{2}', [date_out]='{3}' where visit_detail.v_id={4};", check_inn, checkout, time_out, date_out, v_idd);
But this is still not valid. If time_out contains ' characters, you'll again receive an error.
What you should really use is this:
SqlCommand.Parameters
This is a proper way of passing paramters to your command, all the problems will be taken care of for you.
I'm using SQL Server 2008, with a C# front end. I'm trying to pass a SQL string from C# to SQL Server, and there are 2 fields in my WHERE statement that sometimes might contain NULL values. I've got this code on my Page Load in the code-behind (this is for a report that will be placed in a datagrid):
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection sqlconnectionStatus = new SqlConnection(str);
string DDL_Value = Convert.ToString(Request.QueryString["DDL_Val"]);
string Val_Value = Convert.ToString(Request.QueryString["Val_Val"]);
string Trk_Value = Convert.ToString(Request.QueryString["Trk_Val"]);
string StDt_Value = Convert.ToString(Request.QueryString["StDt_Val"]);
string EnDt_Value = Convert.ToString(Request.QueryString["EnDt_Val"]);
string BTN_Value;
// Because the date is stored as an INT, you have to request the string and then
// convert it to an INT
string StDT_Vals = Request.QueryString["StDt_Val"].ToString();
string EnDT_Vals = Request.QueryString["EnDt_Val"].ToString();
string sqlquery;
sqlquery = "Select DISTINCT PL.PROC_NM as Agent_Name, CCM.UNIQUE_CLAIM_ID as Unique_ID, CCM.CLAIM_ID as Claim_Number, ";
sqlquery = sqlquery + "CCM.SOCSEC as Employee_Last_Digit, CCM.DATE_IMPORTED as Import_Date, CCM.Orig_Open_Date as Original_Review_Date, ";
sqlquery = sqlquery + "AGL.ACCT_GRP as Account_Name, AL.ACCT_NUM as Account_Number, CCM.CDBBEN as Benefit_Option, CCM.BENEFIT_TYPE1 as Benefit_Type1, ";
sqlquery = sqlquery + "CCM.BENEFIT_TYPE2 as Benefit_Type2, CCM.BENEFIT_TYPE3 as Benefit_Type3, CCM.Cmplt as Review_Validated, CCM.Vldtn_Cmmnts as Validation_Comments, ";
sqlquery = sqlquery + "CCM.Gtkpr_Cmmnts as Gatekeeper_Comments, TS.StatusText as Tracking_Status ";
sqlquery = sqlquery + "from ClosedClaims_MERGE CCM ";
sqlquery = sqlquery + "LEFT JOIN PROC_LIST PL ON CCM.Spare = PL.LOGIN ";
sqlquery = sqlquery + "LEFT JOIN ACCT_LIST AL ON AL.ACCT_NUM = CCM.CDBACC ";
sqlquery = sqlquery + "LEFT JOIN ACCT_GRP_LIST AGL ON AGL.ACCT_GRP_PK = AL.ACCT_GRP_FK ";
sqlquery = sqlquery + "LEFT JOIN TrackingStatus TS ON TS.StatusCode = CCM.TrackingStatus ";
sqlquery = sqlquery + "WHERE CCM.Spare LIKE '" + DDL_Value + "' AND CCM.Cmplt LIKE '" + Val_Value + "' AND CCM.TrackingStatus IN (" + Trk_Value + ") AND CCM.DATE_IMPORTED >= '" + StDt_Value + "' AND CCM.DATE_IMPORTED <= '" + EnDt_Value + "'";
}
The code is sound, it works perfectly fine if a value is selected for all report parameters. The problem is CCM.Spare and CCM.Cmplt can have specific values chosen from a dropdown, or they can be left blank. If left blank, then they need to pull ALL values, whether they're NULL or not. When I leave one (or both) blank, that's where the SQL fails.
I tried checking for blanks and setting the variable equal to '%', but that obviously isn't working; it will only pick up records where there is a value in the field.
I want to do this with one statement if possible before I go cludging it with some If/Then/Else loops.
Is this possible?
try this, I just included the code for the first criteria.
As recommended above, don't concatenate your parameters; the second option is the best way to do it:
sqlquery = sqlquery +
"WHERE CCM.Spare " + (DDL_Value == null ? "IS NULL" : "LIKE '" + DDL_Value + "'") + " AND ...";
sqlquery = sqlquery +
"WHERE CCM.Spare " + (DDL_Value == null ? "IS NULL" : "LIKE #par1") + " AND ...";
Additionaly to increase the speed of your query you could do:
sqlquery = sqlquery +
"WHERE " + (DDL_Value != null ? "CCM.Spare LIKE #par1 AND " : "") + "...";
this will ignore the whole criteria on CCM.Spare if your parameter is null.
If you want all possible values of CCM.Spare and CCM.Cmplt, you simply need to leave off the predicate. Build a separate query (preferable using parametrized queries, as marc_s points out) that omits the WHERE clause referencing the empty dropdown value.
I'm experiencing difficulties filtering a set of data between two DateTime values.
For example: Retrieve all records From: 24/04/2013 3:54 PM; To: 24/04/2013 4:30 PM.
I'm programming in C# and using OLE DB to pull data from a Access Database.
The 'To' and 'From' DateTime values are retrieved from DateTimePicker controls on a GUI.
I'm trying to query data in 'receiveDateTime' field of my data source - it is stored in DateTime format in Access.
My code appears as follows:
string SQLQuery = "SELECT EmailID, ServerName, receiveDateTime, Type, status, received, processed"
+ "FROM EmailTable, EmailTypesTable, ServerTable, StatusTable"
+ "WHERE EmailTypesTable.emailTypeID = EmailTypesTable.EmailType "
+ "AND ServerTable.ServerID = EmailTable.serverID "
+ "AND StatusTable.statusID = EmailTable.statusID "
+ "AND EmailTable.receiveDateTime BETWEEN "
+ fromDateTime.Value.ToString("g") + "AND " + toDateTime.Value.ToString("g")";
loadDataGrid(SQLQuery);
Any solutions or advice would be much appreciate.
Thanks,
Allan.
1- It seems you forgot the single quotes between the date values:
string SQLQuery = "SELECT EmailID, ServerName, receiveDateTime, Type, status, received, processed"
+ "FROM EmailTable, EmailTypesTable, ServerTable, StatusTable"
+ "WHERE EmailTypesTable.emailTypeID = EmailTypesTable.EmailType "
+ "AND ServerTable.ServerID = EmailTable.serverID "
+ "AND StatusTable.statusID = EmailTable.statusID "
+ "AND EmailTable.receiveDateTime BETWEEN '"
+ fromDateTime.Value.ToString("g") + "' AND '" + toDateTime.Value.ToString("g") +"' ";
2- It would be better if you use parameterized parameters too:
SqlConnection con = new SqlConnection(MyconnectionString);
con.Open();
string SQLQuery = "SELECT EmailID, ServerName, receiveDateTime, Type, status, received, processed"
+ "FROM EmailTable, EmailTypesTable, ServerTable, StatusTable"
+ "WHERE EmailTypesTable.emailTypeID = EmailTypesTable.EmailType "
+ "AND ServerTable.ServerID = EmailTable.serverID "
+ "AND StatusTable.statusID = EmailTable.statusID "
+ "AND EmailTable.receiveDateTime BETWEEN #dateFrom AND #dateTo";
SqlCommand cmd = new SqlCommand(SQLQuery );
cmd.Parameters.AddWithValue("#dateFrom", fromDateTime.Value.ToString("g"));
cmd.Parameters.AddWithValue("#dateTo", toDateTime.Value.ToString("g"));
SqlDataReader reader = cmd.ExecuteReader();
//...
You could have guessed the issue by trying to execute this query directly in your database
(I have used SQLConnection, SQLCommand... here, you will need to change that part based on the connection you are using.)
For anyone that encounters this problem in future when comparing DateTime value, passing the C# DateTime as an OLE Automation date to the database works!
In order to access this value you use the ToOADate() method.
For example:
SqlConnection con = new SqlConnection(MyconnectionString);
con.Open();
string SQLQuery = "SELECT EmailID, receiveDateTime "
+ "WHERE EmailTable.receiveDateTime "
+ "BETWEEN #dateFrom AND #dateTo";
SqlCommand cmd = new SqlCommand(SQLQuery );
cmd.Parameters.AddWithValue("#dateFrom", fromDateTime.Value.ToOADate());
cmd.Parameters.AddWithValue("#dateTo", toDateTime.Value.ToOADate());
It is quite strange, because although the DateTime values appear in general DateTime Format in the DataGrid, the database must read them as such:
General DateTime Format: 26/04/2013 9:47 AM
OLE Automation Date: 41390.4082198032
Thanks for pointing me in the right direction noobob!
I realize IDataReader is outdated and some view it as dirty code, but on the site I am working on this is what they use. I have an IDataReader statement to run a query to get a specific id from a table using multiple joins. Now this site has a DAL but it only supports the ability to select from one table at a time, so using select statements with joins do not work with it. This is why I am forced to use IDataReader with this.
if (Request.QueryString["CategoryId"].ToString() == "0")
{
using (IDataReader getCategoryID = DB.GetRS("SELECT ItemCatalogCategory.CategoryID FROM UserCustomerCatalog INNER JOIN ItemCatalogCategory ON UserCustomerCatalog.ItemProfileCatalogID = ItemCatalogCategory.ItemProfileCatalogID " +
"INNER JOIN ItemCategory ON ItemCatalogCategory.CategoryID = ItemCategory.CategoryID INNER JOIN StoreCatalog ON UserCustomerCatalog.StoreCatalogID = StoreCatalog.StoreCatalogID " +
"WHERE UserCustomerCatalog.ItemProfileCatalogID = '" + Request.QueryString["CatalogID"] + "' AND UserCustomerCatalog.CustomerID =' " + Session["Customer"].ToString() + "' AND ItemCategory.ProductID = '" + productis + "'"))
{
if (getCategoryID.Read())
{
string categoryID = getCategoryID["ItemCatalogCategory.CategoryID"].ToString();
string lookmike = Request.Url.AbsolutePath + "?CatalogID=" + catalogis + "&ProductID=" + productis + "&CatalogIndex=" + Request.QueryString["CatalogIndex"] + "&CategoryID=" + categoryID;
Response.Redirect(Request.Url.AbsolutePath + "?CatalogID=" + catalogis + "&ProductID=" + productis + "&CatalogIndex=" + Request.QueryString["CatalogIndex"] + "&CategoryID=" + categoryID);
}
else
{
Response.Redirect(Request.Url.AbsolutePath + "?CatalogID=" + catalogis + "&ProductID=" + productis + "&CatalogIndex=" + Request.QueryString["CatalogIndex"] + "&CategoryID=" + Request.QueryString["CategoryId"]);
}
}//end using getCategoryID
}
this is what I have, but when it gets to:
if (getCategoryID.Read())
it renders as false, there are no exceptions thrown, and no errors or warnings. I have done this type of select in the past with no problems, but I cannot figure out why .Read() is returning false.
Can anyone suggest possible reasons for it not reading? If more code is needed, I can provide as needed. Any help is appreciated, thank you in advance.
Looking at your SQL text there is a little typo that could wreak havoc with the results
"WHERE UserCustomerCatalog.ItemProfileCatalogID = '" + Request.QueryString["CatalogID"] +
"' AND UserCustomerCatalog.CustomerID =' " + Session["Customer"].ToString() + "' AND ..... "
here ^
That space mangles your query and give no result.
Let me also repeat that you have a problem with SQL Injection as other members have already said. You could add an overload to your actual implementation of GetRS that receive also a SQLParameter collection to add to the command used to build your SqlDataReader. Something like this
public SqlDataReader GetRS(string sqlText, SqlParameter[] prm)
{
....
SqlCommand cmd = new SqlCommand(sqlText, conn);
cmd.Parameters.AddRange(prm);
.....
}
and then start to upate the calling code.