SQL Query returning all table columns - c#

SqlCommand query = new SqlCommand();
query.Connection = dbconn;
try {
query.CommandText = "SELECT email,LastSync FROM users WHERE email IN ('alexander#contoso.com')";
sdr = query.ExecuteReader();
while(sdr.Read()) if(!sdr.IsDBNull(1)) syncedUsers.Add(sdr.GetString(0));
sdr.Close();
} catch(Exception e) {
logger.Log(e.Message);
List<string> fields = new List<string>();
if(sdr!=null) for (int i = 0; i < sdr.FieldCount; i++)
{
fields.Add(sdr.GetName(i));
}
logger.Log(String.Join(",",fields));
}
This sometimes (not always) throws the error:
Unable to cast object of type 'System.Int32' to type 'System.String'.
and the one time that I looked, the logging then contained a list of all fields of the table, not only the two requested fields:
id,email,LastSync,...
although the query is about two columns only. id is an int, email is a string, so I assume that the error is thrown in GetString(0). The error is not reliably reproducible, I did not yet get it while VS debugging was enabled.
Now, as long as that reader is open, the field list cannot change, or so I think. Is it possible under certain circumstances that the SQL Server returns more fields than I requested?
It is a SQL Server Express 2012.
I know that this can be "solved" by using column names instead of indexes, but before I do, I want to make sure that this is really the issue. I cannot reproduce the issue across all machines I deployed the code to, only certain machines seem to be affected (it doesn't seem to depend on the # of cores available to the machine, nor on the operating system or the .NET version)
EDIT: I now have the same problem when using ExecuteScalar(), on the same table. Doesn't happen with other tables, as far as I can see. I try to get a string using the query
SELECT displayName FROM users WHERE email=#email
using ExecuteScalar(), and sometimes the result is 4, which is the id of the row I requested. So it seems to get the right row, but not the right columns.
This is really weird!

Related

Not getting results from database

In my C# code, I'm trying to open a connection to a SQL Server database and get a count. I've copied the code (barring the query itself) from another application I wrote that works fine. I've run the query -- both the version I constructed, and the query the code constructs (I use variables) -- and they both work fine, returning an identical count. I'm just not getting anything back.
I've put in breakpoints and checked my connection and query, and it is what I expect. When I Googled this, I just got results for people having entirely different problems, so I'm stumped. I don't know why I'm not getting anything back. Where is the error?
SqlConnection RRconnection = new SqlConnection();
RRconnection.ConnectionString = "Data Source=;Initial Catalog=;User id=;Password=";
RRconnection.Open();
string ridQuery = "SELECT COUNT (t.RxTimeStamp) FROM...";
SqlCommand query = new SqlCommand(ridQuery, RRconnection);
SqlDataReader data = query.ExecuteReader();
if (data.Read())
transcount = Convert.ToInt32(data.GetValue(0));
In case the above paragraph wasn't clear, I'm expecting the query to return a count of 1592064 (for the specific instance I'm testing), and instead there's no data in data.
Probably not related, but my query includes three inner joins. It's the first time I've done that many, so maybe that could be the problem? Except if that was causing the problem, it wouldn't work when I run the query?
have you tried using SqlCommand.ExecuteScalar Method
SqlCommand query = new SqlCommand(ridQuery, RRconnection);
Int32 transcount = (Int32) query.ExecuteScalar();
Update
I am not sure why your query did not work, maybe try giving the count column an alias:
string ridQuery = "SELECT COUNT (t.RxTimeStamp) AS RxCount FROM ...";
It is best to use ExecuteScalar if the query returns a single value.
ExecuteScalar; return object value so must be Convert to the correct type
int totalCount = Convert.ToInt32(cmd.ExecuteScalar());
So, to the you question
It's a ExecuteReader don't use to get a Select Count result, but there's no problem this code. You can see the total count value for this code.
Note : The SqlDataReader Object is a stream-based and forward-only retrieval of query results from the Data Source.
The Read method processes only one row in memory then overwrites old record when itterate next row.
ExecureReader; In your case , reader first row and first column filled query result, other rows and column set to null.
if(reader.Read())
{
int totalRows = Convert.ToInt32(reader.GetValue(0)); //convert returned value
}
Note : use column name and use reader spesific type convert method is my best choice.
reader.GetInt32(reader.GetOrdinal("TotalCount"))
Advice,
Don't use ExecuteReader read for single value
Use ExecuteScalar then cast result to correct type
Use IDisposible objects (Connection , Command , Reader) inside to using code blog. using block close and dispose current object.
You should not read using code blog on column index value

VFPOleDb schema returned but no results in C#

I'm at the end of my rope on this issue. Trying to connect to a FoxPro directory hosted locally, using the Microsoft OLE DB Provider for Visual FoxPro 9.0 with the following code:
using (var con = new OleDbConnection(#"Data Source=C:\FoxDB;Provider=VFPOLEDB.1;"))
{
con.Open();
using (var cmd = new OleDbCommand("select * from order", con))
{
var dr = cmd.ExecuteReader();
while (dr.Read())
{
Debug.WriteLine(dr["ord_id"]);
}
}
}
Executing the code does not throw an exception, but there are zero rows returned. The schema is discovered and returned, as it has 72 fields present when I examine the data reader (I've done the same with data tables, data sets, data adapters, etc. All return the schema, but zero results).
Building an SSIS package to access the same table and pull into a MSSQL database results in 3,828 records being pulled in. order.dbf on disk is 884kb which seems to jive with the SSIS results I've pulled in.
I've tried adding Collation Sequence to the connection string, both Machine and General to no effect.
Please tell me there's something obvious I'm missing!
UPDATE: So apparently there's something that I just don't understand about FoxPro. If I change the command type to CommandType.TableDirect and switch the command text to just be order, it returns all the rows. Any insight would be appreciated.
I think the problem is not with Foxpro, testing with the same exact code, I can get the result (created a free test table in c:\FoxDb). Ensure that you are using the latest VFPOLEDB driver. It looks like the problem lies within your table.
BTW, order is a keyword, you better write it as:
"select * from [order]"
although it would work as you did (VFP is forgiving in that regard). The problem might also lie in collation sequence you have used (I never use collation sequences other than machine, they are problematic in Turkish, I expect the same in some other languages).

'System.StackOverflowException' occurred in System.Data.SqlServerCe.dll

I'm using SQL CE 4.0 and am running into a StackOverflowException when the SqlCeDataAdapter attempts to Fill the DataTable.
The code is pretty standard :
using (var cmd = new SqlCeCommand(sql, conn, tran))
using (var dt = new DataTable())
{
using (var da = new SqlCeDataAdapter(cmd))
da.Fill(dt);
IList<DataRow> rows = dt.Rows.OfType<DataRow>().ToList();
foreach (DataRow row in rows)
{
// Processing ...
}
}
The sql string is in the form of :
SELECT * FROM [Table] WHERE Id IN ( ... )
The total character count is 1,068,369 due to the column value list being filled with 27,393 values of type uniqueidentifier.
Executing that query should return results with 1-for-1 rows from the database. Instead, the StackOverflowException occurs. I feel as though I am running up against some sort of SQL CE 4.0 limitation.
I've read Understanding Databases (SQL Server Compact) > Database Objects and under the Queries section it reads :
Characters in an SQL statement | Unlimited
1,068,369 characters is less than unlimited; PASS.
I've read DataTable Class and under the Remarks section it reads :
The maximum number of rows that a DataTable can store is 16,777,216
27,393 rows is less than 16,777,216; PASS.
Is there something else that I'm missing?
"The code is pretty standard" (!) - but the SQL statement is not!
It is obviously an engine bug/doc error, but do not expect a fix from Microsoft.
You will have to change the code to work with smaller batches of ids, resulting in a statement that is not 1 MB in size with 27.000 values.
This sounds like your sql server runs out of temp space when running this query. You can test this by changing the query to return only one row and not using the IN statement. if this works then as mentioned before check or ask your DBA to check that the system has been allocated the resources to run the query and build the result set before returning it to your application. PS. IF multiple persons use this application at the same time then this problem will scale horribly.

Supplying a parameter to a GET_LOCK query in a C# Typed TableAdapter query

I am trying to maintain data consistency across multiple automated services accessing a single MySQL (InnoDB) database. Currently, I am trying to accomplish this using GET_LOCK. I am working with auto-generated typed datasets, and have configured the following query:
SELECT GET_LOCK('#id', 1)
The adapter also accepts an Int32 as a parameter. The problem is that the '#id' field is interpreted as a string literal, so I cannot get a dynamically assigned lock string. My question is if this is even possible.
My current workaround is something along the lines of:
DataSetTableAdapters.myTableAdapter typedAdapter = new DataSetTableAdapters.myTableAdapter();
MySql.Data.MySqlClient.MySqlCommand selectCommand_backup = typedAdapter.Adapter.SelectCommand;
typedAdapter.Adapter.SelectCommand = new MySql.Data.MySqlClient.MySqlCommand();
typedAdapter.Adapter.SelectCommand.Connection = typedAdapter.Connection;
typedAdapter.Adapter.SelectCommand.CommandText = string.Format("SELECT GET_LOCK('{0}_{1}', 1)", tableName, id);
typedAdapter.Adapter.SelectCommand.CommandType = System.Data.CommandType.Text;
typedAdapter.Connection.Open();
typedAdapter.Adapter.SelectCommand.ExecuteScalar();
typedAdapter.Connection.Close();
typedAdapter.Adapter.SelectCommand = selectCommand_backup;
I'm also open to other ideas. I want to prevent conflict resolution if possible, since it would be challenging to handle for an automated system.

Does Mono treat System.Data.SqlCommands differently to .NET?

I'm having some trouble with an application that we're porting to Mono.
(For reference, the .NET runtime is 4.0, and the mono version is 2.6.7.)
EDIT: This problem persists on Mono 2.10.2
As part of the startup of the application, it reads data into memory. For this part I'm just using in-line SQL commands, but for some reason, I'm seeing inconsistent behaviour on Linux/Mono (when the whole thing works in Windows/.NET).
I have a query that works fine in some scenarios, but not in others.
This particular example doesn't work:
var cmd = new SqlCommand("SELECT ID, Name, VATTerritoryID, NativeCurrencyID FROM PricingZones", conn);
var reader = cmd.ExecuteReader();
var objectToLoad = new SomeObjectType();
while (reader.Read())
{
objectToLoad.Property1 = reader.GetInt32(row.GetOrdinal("ID"));
objectToLoad.Property2 = reader.GetString(row.GetOrdinal("Name"));
objectToLoad.Property3 = reader.GetInt32(row.GetOrdinal("VATTerritoryID"));
objectToLoad.Property3 = reader.GetInt32(row.GetOrdinal("NativeCurrencyID"));
}
EDIT: For comparison, here's one that does work:
var cmd = new SqlCommand("SELECT VATTerritoryID, ProductDescriptionID, VATBandID FROM VATTerritoryBandExceptions", conn);
var reader = cmd.ExecuteReader();
var someOtherObjectToLoad = new SomeOtherObjectType();
while (reader.Read())
{
someOtherObjectToLoad.Property1 = reader.GetInt32(row.GetOrdinal("VATTerritoryID"));
someOtherObjectToLoad.Property2 = reader.GetString(row.GetOrdinal("ProductDescriptionID"));
someOtherObjectToLoad.Property3 = reader.GetInt32(row.GetOrdinal("VATBandID"));
}
I had possible suspicions that there were differences down to:
Casing (Since I know this is different on windows/linux), but putting everything to lowercase hasn't solved the problem
Column names (perhaps Mono cares more about reserved words?), but it seems replacing Name with [Name] or 'Name' didn't make any different
The error I had in the first case was:
[IndexOutOfRangeException: Array index is out of range.]
at System.Data.SqlClient.SqlDataReader.GetInt32(Int32 i)
Suggesting that there is no "column1" in the returned result set.
(EDIT: updated this section a little for clarity)
Oddly, if I do this:
var cmd = new SqlCommand("SELECT ID, Name, VATTerritoryID, NativeCurrencyID FROM PricingZones", conn);
var reader = cmd.ExecuteReader();
var objectToLoad = new SomeObjectType();
while (reader.Read())
{
Console.WriteLine("First row, first column is " + row.GetValue(0));
Console.WriteLine("First row, second column is " + row.GetValue(1));
Console.WriteLine("First row, third column is " + row.GetValue(2));
Console.WriteLine("First row, fourth column is " + row.GetValue(3));
}
The output is:
First row, first column is 0
First row, second column is New
Array index is out of range.
I assume something strange is happening with the Mono framework in this case, but I can't find a relevant bug report, and I can't identify why this only happens in some cases but not others! Has anyone else had a similar experience?
EDIT: I've changed some of the statements to match those in the failing query exactly, in case there is an issue with reserved words or similar. Note that the query I'm issuing in the second case really does request four columns and seemingly only gets two very odd ones back (0 | New ).
Ok mate I managed to reproduce your problem. You have a threading problem there. That was my only idea what may be the cause of this problem and I managed to actually reproduce it.
In order to fix it you need to do the following:
Make sure every reader has a reader.Close() call after parsing the
data.
Use the following code to do thread-safe calls:
Object executeLock = new Object();
private IDataReader ExecuteThreadSafe(IDbCommand sqlCommand)
{
lock (executeLock)
{
return sqlCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
}
Looks like mono has a different implementation of SQL objects than .NET. It's true that I wasn't able to reproduce it on Windows!
I would start out by trying to figure out exactly where the difference lies.
First off, you have the following code:
objectToLoad.Property1 = reader.GetInt32(row.GetOrdinal("column1"));
objectToLoad.Property2 = reader.GetString(row.GetOrdinal("column2"));
objectToLoad.Property3 = reader.GetString(row.GetOrdinal("column ")); //Is the space on the end intended?
I believe you said the first two lines work, and the third line blows up. We first need to figure out where this blows up. I'd try:
int test = row.GetOrdinal("column ");
Does test equal a valid column index? If not, that's your problem. Make sure that's the exact column name, try different casings, etc. If the index is valid, try:
object foo = reader[test];
Console.WriteLine(foo.GetType().Name);
to figure out what the data type of this column is. Perhaps there's a casting problem.
If that fails, I'd try loading the reader into a DataSet object instead so you can look at the exact schema more carefully.
If you do find a difference in behavior between Mono and the .NET Framework, the Mono team is usually very willing to fix these. I strongly recommend filing this as a bug.
Hope this helps!
Try accessing your reader in this manner:
reader["column1isastring"].ToString();
(Int32)reader["column2isInt32"];
Also, as a side note, make sure you're using the "using" directive for disposable objects. I'm not sure if Mono implements this, but it's worth a shot. What the using directive does is cleans up disposable objects as soon as you're done using them. It's very handy and makes for clean code. Quick example:
using (MySqlCommand command = new MySqlCommand("SELECT column1, column2, column FROM tablename", conn))
{
try
{
conn.Open();
using (MySqlDataReader reader = command.ExecuteReader())
{
reader.Read();
var someString = reader["column1isastring"].ToString();
var whatever = (Int32)reader["column2isInt32"];
} //reader closes and disposes here
}
catch (Exception ex)
{
//log this exception
}
finally
{
conn.Close();
}
} //conn gets closed and disposed of here
Also, if you're getting user input that goes straight to your commands, make sure you use the MySqlParameter class to keep malicious parameters from dropping tables, for example.
Mono is not .NET and there are a lot of differences especially with earlier versions. The root methodology to connect to SQL is using a TDS (tabular data stream) implementation in C# which for earlier versions of Mono (and TDS as a result) can cause a lot of problems. Almost all essential classes for SQL and data are having differences that potentially may cause exceptions. Maybe it's worthy to try with Mono 2.10+ because the Mono team improves the whole project continuously.
I am using Mono 4.0 and I have a similar problem. My research shows, that most probable reason of this problem is flawed implementation of connection pool in Mono. At least, if I switch off pooling, the problem disappears.
To switch off connection pooling you need to add the following string to your connection string: Pooling=false;
After that, creation of connection object should look like that:
var conn = new SqlConnection("Server=localhost; Database=somedb; user=user1; password=qwerty; Pooling=false;");

Categories