C# SqlDataReader only returns values > 0 - c#

This has been bugging me for the past several hours and I can't seem to find the answer..
I have the following query
SELECT A, SUM(B) AS total
FROM table
GROUP BY A
now the column B in table can only hold 0 or 1.
and A is total1, total2 or total3
now when I use this directly in the SQL database I get a nice table holding
A total
total1 1
total2 0
toatl3 5
This is exactly what I want it to do.
However if using in my c# program. if one of the totals is 0 it is not displayed at all..
Below is the code I'm using but it only works fine when total1, total2 and total3 are bigger then 0
so the table above would only display total1 and total3...
string total = "A total";
SqlConnection conn = new SqlConnection("connection string goes here I know");
try
{
conn.Open();
SqlCommand total = new SqlCommand(
"SELECT A, SUM(B) AS total FROM table GROUP BY A", conn);
SqlDataReader total_reader = total.ExecuteReader();
while (total_reader.Read())
{
total += total_reader["A"].ToString() + " " + total_reader["total"] + "\n";
}
}
catch (Exception err)
{
serverstats += err.ToString();
}
finally
{
conn.Close();
}
How can I make it so that it would display the table properly, even if total1, total2 and total3 are 0
thus displaying:
A total
total1 0
total2 0
toatl3 0
I know that a 0 in SQL generally equals to null and such.
I suspect that this is the reason that C# assumes that if the value is 0 that it is not of interest.
I hope I explained it properly enough, thanks for any help in advance!
=======EDIT======
COALESCE or ISNULL does not make a difference :(
I assume it's to do with the C# reader bit not in the SQL querying bit.
As you can see in my example the SQL bit DOES create a table with the correct Rows and does not write them as NULL. But the C# bit seems to read it as NULL.

If column B can have nulls, try
SELECT A, COALESCE(SUM(B),0) AS total
FROM table
GROUP BY A

which sql database are you using? sql server or mysql?
or try to edit the line:
total += total_reader["A"].ToString() + " " + total_reader["total"] + "\n";
to
total += total_reader["A"].ToString() + " " + int.Parse(total_reader["total"].ToString()) + "\n";

Okay turns out that I had WHERE (B = 1)
I forgot to take this out of my SQL query..
Thanks for the help :)

Related

How to append the suffix to be unique if there is a record with the same name in the database?

I'm in trouble with a little problem.
products are listed in the database. In the code column, the data is kept as follows:
"F-01, F-02, F-03, ..., X-99"
Customers may want to add external data to the system, but sometimes they want to add the same record.
To avoid these duplicates, I need to put a distinctive suffix like "-01" at the end of the line of code column.
I am developing this system in c # and I have developed such a logic:
int counter = 1;
var code = "F-" + productEntity.Code;
​
while (await uow.Repository<Product>().Query().AnyAsync(a => a.Code == code) == true)
{
code = code + "-" + counter;
counter++;
}
But what I noticed is that a record I added in the form of F-01-1 will turn into F-01-1-1 when it comes back to me.
I think I missed a very small point, but I can not reach my goal.
The expression code + "-" + counter; appends 3 strings together and return the result.
Say:
code is "F-01"
counter is 1
Then the expression above will be evaluated as such:
"F-01" + "-" + "1", that is "F-01-1"
If you reexecute your method, then the expression will be:
"F-01-1" + "-" + "1" that is "F-01-1-1"
And so on.
The solution is to split the code to extract the last part, which corresponds to the value of the counter. It is done with string[] parts = "F-01-1".Split('-'):
parts[0] = "F"
parts[1] = "01"
parts[2] = "1" which corresponds to the counter
So now int counter = int.Parse(parts[2]) + 1 will return the next value for counter 2.
And you can have your full code "F-01-2" returned by code = $"{parts[0]}-{parts[1]}-{counter}"

How do I get fields such as "cost" from an estimate query using Quickbooks SDK (QBFC)?

I'm running an estimate query through QBFC on Quickbooks Desktop Edition, and while I'm able to pull some fields that I see on the Estimate screen in Quickbooks, there are other fields that I am not able to pull/find. Furthermore, some attributes I'm pulling don't match the values I'm expecting.
My code is here:
...
IEstimateQuery estimateQuery = msgSetReq.AppendEstimateQueryRq();
estimateQuery.OwnerIDList.Add("0");
estimateQuery.ORTxnQuery.TxnFilter.EntityFilter.OREntityFilter.FullNameList.Add("testcustomer");
estimateQuery.IncludeLineItems.SetValue(true);
IMsgSetResponse msgSetResp = sessionManager.DoRequests(msgSetReq);
IResponse resp = msgSetResp.ResponseList.GetAt(0); //a list of responses for each request - we only sent one request so get the first response
IEstimateRetList estimateList = (IEstimateRetList)resp.Detail;
for(int i=0; i < estimateList.Count; i++) {
IEstimateRet estimate = estimateList.GetAt(i);
Debug.WriteLine("est name: " + estimate.CustomerRef.FullName.GetValue());
Debug.WriteLine("est subtotal: " + estimate.Subtotal.GetValue());
Debug.WriteLine("est total: " + estimate.TotalAmount.GetValue());
if(estimate.DataExtRetList != null) {
for(int j=0; j<estimate.DataExtRetList.Count; j++) {
string fieldName = estimate.DataExtRetList.GetAt(j).DataExtName.GetValue();
string fieldValue = estimate.DataExtRetList.GetAt(j).DataExtValue.GetValue();
Debug.WriteLine("--- " + fieldName + " : " + fieldValue);
}
}
if(estimate.OREstimateLineRetList != null) {
for (int j = 0; j < estimate.OREstimateLineRetList.Count; j++) {
IEstimateLineRet lineRet = estimate.OREstimateLineRetList.GetAt(j).EstimateLineRet;
if(lineRet.Amount != null) {
Debug.WriteLine("total [" + j + "] " + lineRet.Amount.GetValue()); //for some reason amount is estimated par total
if (lineRet.Desc != null) {
Debug.WriteLine("description row [" + j + "] " + lineRet.Desc.GetValue());
}
}
//lineRet.DataExtRetList is null, I've checked
}
}
}
I'd get an example output of:
est name: testcustomer
est subtotal: 6996.07
est total: 6996.07
--- Net Income : 6530.24
--- Other : 8036
total [0] 4451.1
description row [0] Test item1
total [1] 1952.5
description row [1] Test item2
...
You'll notice above that I log lineRet.Amount's value, but if you look at this picture I've attached, amount is actually giving me the red circle on the far right column as opposed to the green circle (under the 'Amount' column).
When I log subtotal and total, I expect to see both the green and red circles near the bottom, but instead I'm getting the value of the red circle twice (subtotal is not coming out correctly).
Finally, I am unable to get the "Cost / Unit" column (which was originally named 'Cost' I believe).
Any ideas on how to access these fields, or why some fields seem to be pulling the wrong values?
Thank you in advance for your time.
According to the documentation:
Subtotal
The total of all the estimate lines before taxes are applied.
(By contrast, a subtotal item (an ItemSubtotal object) gives only the
total of the amounts in the lines that appear above it.)
Thus, it looks like the "Subtotal" in the SDK has a different meaning from the "Subtotal" in the UI. In the SDK, the subtotal means the pre-tax total. In the UI, it means the pre-markup total.
I think the only way to get the pre-markup total using the SDK is to iterate over each line and total it yourself.
// Somewhere outside your loop
double premarkupSubtotal = 0;
// ...
// Within your loop
premarkupSubtotal += (lineRet.ORRate.Rate.GetValue() * lineRet.Quantity.GetValue());
Note that the line's Amount property seems to represent the total amount (rate * quantity * markup). Thus, to find the pre-markup total for each line, we can just multiple the line's rate by its quantity instead.
With regards to the Cost / Unit, this seems to be the rate for each line. This can be retrieved using:
lineRet.ORRate.Rate.GetValue()

My working hours cannot work due to my syntax from database

I'm really confuse about this syntax. I want to cast my in and out to get the total hours of work but it is not working.
Here's my code:
con.Open();
MySqlDataAdapter sda = new MySqlDataAdapter("Select name , logdate as 'Date' , min(logtime) as 'IN', max(logtime) as 'OUT'," +
"CAST(((strftime('%s', max(logtime) ) - strftime('%s', min(logtime) )) % (60 * 60 * 24)) / (60 * 60) AS TEXT) || ':' || " +
"CAST((((strftime('%s', max(logtime) ) - strftime('%s' , min(logtime) )) % (60 * 60 * 24)) % (60 * 60)) / 60 AS TEXT) as 'workHrs' " +
"from Attendance1 group by name, logdate order by logdate", con);
DataTable data = new DataTable();
sda.Fill(data);
dataGridView1.DataSource = data;
con.Close();
Your query contains this:
CAST(some expression AS TEXT) || ':' || CAST(another expression AS TEXT)
But || is Oracle string concatenation. In MySQL use CONCAT() instead.
If you look at your error message carefully you'll see that MySQL gacks near the ||.
It looks like you're trying to use strftime() to do time arithmetic. But strftime() isn't part of either C# or MySQL. It looks like you want to know the elapsed time between two TIME values, MAX(logtime) and MIN(logtime).
You want
TIMEDIFF(MAX(logtime), MIN(logtime))
and to format the result nicely as 1:59 you want
DATE_FORMAT(TIMEDIFF(MAX(logtime), MIN(logtime)), '%k:%i')
Pro tip: Bookmark this page on string functions: https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat
And bookmark this page on date/time functions: https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format

Check values in DataTable

I have a DataTable dtOne, having records as below:
ColumnA ColumnB ColumnC
1001 W101 ARCH
1001 W102 ARCH
1002 W103 CUSS
1003 W104 ARCH
And another DataTable dtTwo, having values as:
ColumnA
ARCH
CUSS
I need to check whether values of dtTwo exist in dtOne or not, if not write it on the webpage.
I wrote the below code, but it doesn't work properly. I need to check like, if ARCH from dtTwo table is present in dtOne, don't check further, just write it to the webpage.
for (int counter = 0; counter < dtTwo.Rows.Count; counter++)
{
var contains=dtOne.Select("ColumnC= '" + dtTwo.Rows[counter][0].ToString() + "'");
if (contains.Length == 0)
{
Response.Write("CostCode "+dtTwo.Rows[counter][0].ToString()+" not present in the Excel");
}
}
Experts please help.
EDIT:
My functionality is achieved when I write the below code, but get a warning that unreachable code detected at counter variable.
I don't think its correct.
for (int counter = 0; counter < dtTwo.Rows.Count; counter++)
{
var contains=dtOne.Select("ColumnC= '" + dtTwo.Rows[counter][0].ToString() + "'");
if (contains.Length == 0)
{
Response.Write("CostCode "+dtTwo.Rows[counter][0].ToString()+" not present in the Excel");
}
break;
}
Regards
According to your clarification, you want to stop if you find a match from the second table in the first table.
Then you need to add the break statement when your Select finds one or more rows that matches the condition
for (int counter = 0; counter < dtTwo.Rows.Count; counter++)
{
var contains=dtOne.Select("ColumnC= '" + dtTwo.Rows[counter][0].ToString() + "'");
if (contains.Length != 0)
{
Response.Write("CostCode "+dtTwo.Rows[counter][0].ToString()+" not present in the Excel");
break;
}
}
From the C# reference
The break statement terminates the closest enclosing loop or switch
statement in which it appears. Control is passed to the statement that
follows the terminated statement, if any.

There is insufficient system memory to run this query when creating temporary table

StringBuilder query = new StringBuilder();
query.Append("CREATE TABLE #Codes (Code nvarchar(100) collate database_default ) ");
query.Append("Insert into #Codes (Code) ");
int lengthOfCodesArray = targetCodes.Length;
for (int index = 0; index < lengthOfCodesArray; index++)
{
string targetCode = targetCodes[index];
query.Append("Select N'" + targetCode + "' ");
if (index != lengthOfCodesArray - 1)
{
query.Append("Union All ");
}
}
query.Append("drop table #Codes ");
on: cmd.ExecuteReader() I get
There is insufficient system memory to run this query when creating temporary table
But weird thing is that, when I have 25k codes is ok, when 5k I get this error.
Initial size is 262 MB.
Lengt of each code is average 15.
This produces one giant statement, and of course it fails eventually.
You should do your INSERT one at a time (no UNION ALL), at least until it's time to optimize.
I have a feeling that your ultimate answer is going to involve BULK INSERT, but I don't know enough about your application to be sure.

Categories