I am trying to figure out how to collect data from a database with c#.
I am stuck on a SQL command, and I can't really figure out how to fix it.
My error is: Invalid Column Name
This is my database:
MyDatabase
And this is my connection class:
namespace CarDAL
{
public class ConnectionClass
{
private string Connectionstring =
"MYCONNECTIONSTRING";
public List<string> SoortSelectList(string KarakterSoort)
{
KarakterSoort = "Defensive";
List<string> soortList = new List<string>();
using (SqlConnection connection = new SqlConnection(Connectionstring))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand("SELECT * FROM dbo.Karakter WHERE KarakterSoort = Defensive", connection))
{
using (IDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
soortList.Add(dr.GetValue(0).ToString());
soortList.Add(dr.GetValue(1).ToString());
}
}
}
}
return soortList;
}
I think after WHERE that the problem is, but I don't know (and can't find) the right solution for my problem.
Your WHERE clause here:
WHERE KarakterSoort = Defensive
compares the value in the KarakterSoort column to the value in the Defensive column.
Is that really what you want???
Quite possibly, you want to compare to a string literal - then you need to put this into single quotes like this:
WHERE KarakterSoort = 'Defensive'
Now you're selecting all rows where the KarakterSoort column contains the value Defensive
Or if you might want compare to some other value in the future - use a parameter in your query string:
WHERE KarakterSoort = #DesiredValue
and declare it
cmd.Parameters.Add("#DesiredValue", SqlDbType.VarChar, 100);
and set its value before your run the command:
cmd.Parameters["#DesiredValue"].Value = "Defensive";
Related
In a C# program with .NET framework to make a windows form I have added the following code to make a connection and to get the value of result and store in a list for later usage
public List<Info> GetInfo(string Col)
{
string connectionString = "Server=VIS-12\\TESTSQLSERVER;Database=SPCC;User Id=sa;Password=admin1234;";
string comand = $"select {Col} from Tbl_Reading where [LogTime] between '2017-07-06 14:30:26.000' and '2017-07-06 14:30:26.000' ";
using (SqlConnection conn = new SqlConnection())
{
double[] val1 = new double [100] ;
conn.ConnectionString = connectionString;
conn.Open();
SqlCommand c1 = new SqlCommand(comand, conn);
SqlDataReader reader = c1.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
int x = 0;
val1[x] = Convert.ToDouble(reader.GetDouble(0)); //this line is throwing the error
x++;
}
}
reader.Close();
List<Info> d1 = new List<Info>();
d1 = (List<Info>)val1.Cast<Info>();//ToList();
conn.Close();
return d1;
//return val1;
}
}
I still keep getting an invalid cast Exception even though the return type and the variable type is same
GetDouble does indeed return type double but there has to be a double value to get. Internally, that method will get an object reference from the specified column and cast it as type double. It is that cast that is invalid, not one that you're performing. If you look at the stack trace of the exception then you should be able to see that.
Either the column you're retrieving is the wrong data type or at least one row contains NULL in that column. If the data type is correct then you need to either filter out NULL values in your query or else account for them in your reading code.
GetDouble will throw an exception if the value internally is not a double. This will happen obviously if the column is a different type, but also if the value is a null. So you need to handle that case.
Other notes:
if (reader.HasRows) is not necessary as you can use reader.Read() to tell you the same thing.
Use a multi-line string with # to make your query more readable.
I hope Col is not coming from user-input, otherwise you have a major injection vulnerability.
You are missing using blocks to dispose your objects.
There seems to be no need for the array, just convert each value as you go along and insert into a list.
between doesn't seem to make sense here, also you should probably use a parameter for the date. If there is really a start and end time, use >= AND < rather than BETWEEN.
Consider putting the connection string in a settings file, rather than hard-coding it.
public List<Info> GetInfo(string Col)
{
string connectionString = "Server=VIS-12\\TESTSQLSERVER;Database=SPCC;User Id=sa;Password=admin1234;";
string comand = #$"
select {Col}
from Tbl_Reading
where LogTime = #time;
";
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand c1 = new SqlCommand(comand, conn))
{
c1.Parameters.Add("#time", SqlDbType.DateTime).Value = DateTime.Parse("2017-07-06 14:30:26.000");
List<Info> d1 = new List<Info>();
conn.Open();
using (SqlDataReader reader = c1.ExecuteReader())
{
while (reader.Read())
{
d1.Add((reader[0] as double) as Info);
}
return d1;
}
}
Hello everyone I am currently working on some testing project and I am having a little problem. Using selenium, I need to SendKey in specific element but instead of fixed value i need to use value (data) from my database. Can anyone help me with how to retrieve single value from database and store it in a variable so i can use it later.
Thank you and sorry for a noobish question - see code below:
SqlConnection conn = new SqlConnection();
SqlCommand command;
SqlDataReader dataReader;
conn.ConnectionString = "Server=******;Database=****;User ID=sqlserver;password=****;MultipleActiveResultSets=true;");
string query = "select RequestID, from AutomaticPayment where RequestID ='1230322'";
DataTable dt = new DataTable();
command = new SqlCommand(query, conn);
conn.Open();
dataReader = command.ExecuteReader();
dt.Load(dataReader);
driver.FindElement(By.Id("requestID")).SendKeys(VALUE FROM DATABASE);
You can use the following code
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlDataAdapter sda = new SqlDataAdapter(query, connection);
connection.Open();
SqlCommand cmd = new SqlCommand(query, connection);
try
{
result = cmd.ExecuteScalar().ToString();
}
catch(NullReferenceException n)
{
result = "";
}
}
ExecuteScaler gets you the first column of the first row and additional columns are ignored. Use the value from result in your SendKeys()
Use conditions to limit the result:
Select data
SELECT TOP 1 RequestID FROM AutomaticPayment // Always returns 1 row
Or
SELECT RequestID FROM AutomaticPayment WHERE Id = 123 // Id must be unique to return 1 row
And maybe other ways.
Get value
var value = dt.Rows[0][1];
Or
var value = dt.Rows[0]["RequestID"];
From what i worked on with SqlCommand just do the following :
int yourId = 0;
dataReader = command.ExecuteReader()
while(dataReader.Read())
{
yourId = dataReader.GetInt32(0);
}
With that, you should have your value set to the first column of the dataReader. (that is selected thanks to your query, since you are requesting on a specific id, i guess it will return only one column
there is many other type available for Reader : Reader Microsoft Doc
And if you have in the futur many data to collect, use the ORM entity framework, work well for me
Source
EDIT :
Since you are only querying one data, maybe the solution of #work_ishaan is better than mine in this case, check it out.
Hi I am trying to create CRUD functions in C# but am stuck on my first one which is FetchALL, as so far it says not all code path returns a value.
Heres my code so far
public SqlDataReader FetchAll(string tableName)
{
using (SqlConnection conn = new SqlConnection(_ConnectionString,))
{
string query = "SELECT * FROM " + tableName;
SqlCommand command = new SqlCommand(query, conn);
using (SqlDataReader reader = command.ExecuteReader())
conn.Open();
conn.Close();
}
}
}
}
I can give you more information, thanks
You have a return type of SqlDataReader, but you aren't returning anything anywhere in your code. At the very least you should declare your data reader and return it like this:
public SqlDataReader FetchAll(string tableName)
{
SqlDataReader reader;
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
string query = "SELECT * FROM " + tableName;
// added using block for your command (thanks for pointing that out Alex K.)
using (SqlCommand command = new SqlCommand(query, conn))
{
conn.Open(); // <-- moved this ABOVE the execute line.
reader = command.ExecuteReader(); // <-- using the reader declared above.
//conn.Close(); <-- not needed. using block handles this for you.
}
}
return reader;
}
Note, I've noted a few other problems I saw as well, which you can see by my comments.
Also, I want to point out something very important: you should always avoid string concatenation in queries as this opens you up to the risk of a SQL injection attack (as gmiley has duly pointed out). In this case, you should create an enum which contains values associated with all the possible table names, and then use a dictionary to look up the table names based on their enum values. If a user provides an invalid/unknown value, you would then thrown an argument exception.
This isn't the end of your problems, though (as Default has pointed out). You can't create the connection in a using block, which disposes and closes as soon as it exits the block, and then use the SqlDataReader that is returned from the method. If I were you, I'd return a DataSet instead of a SqlDataReader. Here's how I'd do it:
First, create your enum of possible table values:
public enum Table
{
FirstTable,
SecondTable
}
And a dictionary that maps table enum values to the table names (which you will populate in your static constructor):
private static Dictionary<Table, string> _tableNames = new Dictionary<Table, string>(); // populate this in your static constructor.
And then here is your method to fetch the data:
public static System.Data.DataSet FetchAll(Table fromTable)
{
var ret = new System.Data.DataSet();
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString))
{
string tableName = "";
if (!_tableNames.TryGetValue(fromTable, out tableName)) throw new ArgumentException(string.Format(#"The table value ""{0}"" is not known.", fromTable.ToString()));
string query = string.Format("SELECT * FROM {0}", tableName);
using (var command = new System.Data.SqlClient.SqlCommand(query, conn))
{
using (var adapter = new System.Data.SqlClient.SqlDataAdapter(command))
{
adapter.Fill(ret);
}
}
}
return ret;
}
One final note, I'd advise you name your class-level variables with lower camel case per convention, e.g. _connectionString.
Firstly you aren't returning anything from the method. I'd add, are you sure you want to return a SqlDataReader? It is declared within a using block, so it will be closed by the time you return it anyway. I think you should re-evaluate what this function should return.
You need a return statment for the method to return a value.
I am trying to populate a data table from a database table. After it is populated i am using asp:GridView to show the data.
The problem is I am trying to edit some rows after it is populated from the database but before binding the data.
I am very new to c# so i cant get it working. My code does not update anything.
private void BindGridviewFileData()
{
string ConnectionStringName = WebConfigurationManager.ConnectionStrings["LocalConnection"].ConnectionString;
try
{
using (SqlConnection sqlConn = new SqlConnection(ConnectionStringName))
{
using (SqlCommand sqlCmd = new SqlCommand())
{
sqlCmd.CommandText = "SELECT * FROM VISUALISATION";
sqlCmd.Connection = sqlConn;
sqlConn.Open();
SqlDataReader objDataReader = sqlCmd.ExecuteReader();
DataTable objDataTable = new DataTable();
objDataTable.Load(objDataReader);
foreach (DataRow row in objDataTable.Rows)
if (row["lineNumber"] == "1")
row["BATCH_NO"] = "new Value";
gvSubjectDetails.DataSource = objDataTable;
gvSubjectDetails.DataBind();
sqlConn.Close();
}
}
}
catch { }
}
The lineNumber check probably needs to be an int check; note that currently it is actually doing an object check, which only supports reference equality - it will never match, even if the value is a string of "1", because the value from the database will become a different string instance than the interned literal "1" from the code. So, the first check probably needs to be:
if((int)row["lineNumber"] == 1)
You ask in comments how to do this with a string; in that case, quite similarly:
if((string)row["BATCH_NO"] == "some value")
This now works because there is an overloaded == operator for string==string, which does a value based equality test, not a reference-based equality test.
Note: you could also probably use:
if(Equals(row["BATCH_NO"], "some value"))
but I find the earlier version clearer.
I need syntax help with the following code logic:
I have a code block that gets email address from the database. The email addresses need to be assigned to a string variable strEmailAddress with a comma seperation
My code is:
SqlConnection conn = new SqlConnection(strConn);
string sqlEmailAddress = "usp_Get_Email_Address";
SqlCommand cmdEmailAddr = new SqlCommand(sqlEmailAddress, conn);
cmdEmailAddr.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataReader sqlDREmailAddr = cmdEmailAddr.ExecuteReader();
How can I loop through the records and store the results in strEmailAddress seperated by comma?
while (sqlDREmailAddr.Read())
{
//...process each row here
}
I would also wrap the reader in a using statement to make sure it is closed properly:
using (SqlDataReader sqlDREmailAddr = cmdEmailAddr.ExecuteReader())
{
}
Depending on what the columns in your dataset is named, reading values from each record will look something like this (update: now with all addresses merged):
var emailAddress = new StringBuilder();
var emailAddressOrdinal = sqlDREmailAddr.GetOrdinal("EmailAddress");
while (sqlDREmailAddr.Read())
{
if (emailAddress.Length > 0)
emailAddress.Append(',');
emailAddress.Append(sqlDREmailAddr.GetString(emailAddressOrdinal));
}
Use the SqlDataReader.Read method:
while (sqlDREmailAddr.Read())
{
...
// Assumes only one column is returned with the email address
strEmailAddress = sqlDREmailAddr.GetString(0);
}
while (sqlDREmailAddr.Read())
{
// handle row here
}
This is what you're looking for....
using (SqlConnection conn = new SqlConnection(strConn)){
string sqlEmailAddress = "usp_Get_Email_Address";
using (SqlCommand cmdEmailAddr = new SqlCommand(sqlEmailAddress, conn)){
cmdEmailAddr.CommandType = CommandType.StoredProcedure;
conn.Open(); // Typo Glitch!
using (SqlDataReader sqlDREmailAddr = cmdEmailAddr.ExecuteReader()){
while(sqlDREmailAddr.Read()){
if (!sqlDREmailAddr.IsDBNull(sqlDREmailAddr.GetOrdinal("emailAddr"))){
// HANDLE THE DB NULL...
}else{
strEmailAddress = sqlDREmailAddr.GetSqlString(sqlDREmailAddr.GetOrdinal("emailAddr"));
// Do something with strEmailAddr...
}
}
}
}
}
Notice:
A typo glitch on the conn variable...
A check is made to ensure that the Database value returned is not NULL
A call is made to GetOrdinal to return the column based on emailAddr string value that corresponds to the column from the query for SQL Select...which is an int type) as the parameter for GetSqlString..
Edit: Thanks to John Saunders for pointing out a blooper!
Edit#2: Thanks to Peter Lillevold for pointing out a mis-spelling...
Hope this helps,
Best regards,
Tom.