Visual Studio Database issue with Adapter - c#

When I try to run the program, I get this error and I cant solve it. Is it because I am trying to get the data from the same method.
rivate void populateTableTopping()
{
string query = "SELECT a.Name FROM Toppings a " +
"INNER JOIN Table b ON a.Id = b.ToppingsId " +
"WHERE b.TypeId = #TypeId";
using (Connection = new SqlConnection(connectionstring))
using (SqlCommand command = new SqlCommand(query, Connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("#TypeId", sizeTypeListBox.SelectedValue);
DataTable tableToppingTable = new DataTable();
adapter.Fill(tableToppingTable);
tableToppingListBox.DisplayMember = "Name";
tableToppingListBox.ValueMember = "Id";
tableToppingListBox.DataSource = tableToppingTable;
}
}
and get this error: in Adapter.fill
System.ArgumentException: 'No mapping exists from object type System.Data.DataRowView to a known managed provider native type.'

sizeTypeListBox.SelectedValue is a System.Data.DataRowView and TypeId is not. They don't match.
Do you want the displayed text?
var text = sizeTypeListBox.GetItemText(sizeTypeListBox.SelectedItem);
command.Parameters.AddWithValue("#TypeId", text);

Related

Windows Forms get data from database and display in label

I want to grab data from database and display in labels based on what the user selects in the list view.
I'm going off an example that does this with two list views, but I don't know how to do it when I'm sending data to a label.
This is the list view example I'm using (my label code is below this)
private void PopulateRecipeIngredients()
{
string query = "SELECT a.Name FROM Ingredient a " +
"INNER JOIN RecipeIngredient b ON a.Id = b.IngredientId " +
"WHERE b.RecipeId = #RecipeId";
// # is a parameter
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
// whatever recipe is selected in lstRecipes box, get the id of that and pass into query above
command.Parameters.AddWithValue("#RecipeId", lstRecipes.SelectedValue);
// DataTable holds the data return from query
DataTable ingredientTable = new DataTable();
// SqlDataAdapter object adapter fills the ingredientTable DataTable object with results from query
adapter.Fill(ingredientTable);
// Display value of Name ex. salad
lstIngredients.DisplayMember = "Name";
// Id column is how we reference
lstIngredients.ValueMember = "Id";
// connect list box on form to data in recipeTable
lstIngredients.DataSource = ingredientTable;
}
}
MY CODE:
private void PopulateCourseDetails()
{
string query = "SELECT * FROM Course_Info WHERE Id = #CourseId";
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("#CourseId", lstCourses.SelectedValue);
DataTable courseTable = new DataTable();
adapter.Fill(courseTable);
lblCourseId.Text = "Course_id";
lblCourseSection.Text = "Course_section";
lblCourseName.Text = "Course_name";
lblCourseDay.Text = "Course_day";
lblCourseStartTime.Text = "Course_start_time";
lblCourseEndTime.Text = "Course_end_time";
lblCourseProfessor.Text = "Course_professor";
lblCourseProfessorEmail.Text = "Course_professor_email";
lstCourses.ValueMember = "Id";
}
}
lblCourseId.Text = (string)courseTable.Rows[0]["Course_id"]
should work as long as you have one row in the result table
Assuming that your DataTable has now been properly populated, you now have a table with a number of rows.
First you need to pull out the first row
var row = courseTable.Rows.FirstOrDefault();
Now you've got a row with a number of columns. You can access each column by either index or column name.
lblCourseId.Text = row[0];
If you want the label to maintain it's header, you can do something like
lblCourseId.Text = "Course_id: " + row[0];

how to reference columns in sql server connection in C#

I'm trying to translate some perl code into C# and I'm having some trouble with the following.
After establishing a sql server connection and executing the select statement, how do I reference the different elements in the table columns. For example, in Perl it looks like:
my $dbh = DBI -> connect( NAME, USR, PWD )
or die "Failed to connect to database: " . DBI->message;
my $dbname = DB_NAME;
my $dbschema = DB_SCHEMA;
my $sql = qq{select a,b,c,d,e,f,g,h,i,...
from $dbname.$dbschema.package p
join $dbname.$dbschema.package_download pd on p.package_id = pd.package_id
join $dbname.$dbschema.download d on pd.download_id = d.download_id
where p.package_name = '$package'
--and ds.server_address like 'tcp/ip'
order by a,b,c,d,..};
my $sth = $dbh -> prepare( $sql )
or die "Failed to prepare statement: " . $dbh->message;
$sth -> execute()
or die "Failed to execute statement: " . $sth->message;
#now to go through each row in result table
while ( #data = $sth->fetchrow_array() )
{
print "$data[0]";
# If source server FTP is not already open, make new FTP
if ( $data[0] != $src_id )
{
if ( $src_ftp )
{ $src_ftp -> quit; }
$src_ftp = make_ftp( $data[1], $data[2], $data[3], $data[18], $data[19], $data[20] );
$src_id = $data[0];
}
}
so far I've got it down to
string db = NAME;
string myConnectionString = "Data Source=ServerName;" + "Initial Catalog=" + db + "User id=" + ODBC_USR + "Password=" + PWD
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myInsertQuery = "select a,b,c,d,e,f,g,h,i,...
from $dbname.$dbschema.package p
join $dbname.$dbschema.package_download pd on p.package_id = pd.package_id
join $dbname.$dbschema.download d on pd.download_id = d.download_id
where p.package_name = '$package'
--and ds.server_address like 'tcp/ip'
order by a,b,c,d,..";
SqlCommand myCommand = new SqlCommand(myInsertQuery);
myCommand.Connection = myConnection;
myConnection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
but how do I reference the columns like data[0] and data[1] in C#. Sorry I'm new to both languages so my background is severely lacking. Thanks!
You could reference your column directly by its column name or by numeric order (it starts with 0 as the first column) either through a DataTable, DataSet, DataReader or a specific DataRow.
For the sake of example i'll use a DataTable here and I will name it as dt and let's say we want to reference the first row then you could reference it with the following Syntax/Format:
dt[RowNumber]["ColumnName or Column Number"].ToString();
For example:
dt[0]["a"].ToString();
Or by number the first column with be 0 like:
dt[0][0].ToString();
And use Parameters by the way because without which it would be susceptible to SQL Injection. Here's a more complete code below:
string db = NAME;
string myConnectionString = "Data Source=ServerName;" + "Initial Catalog=" + db + "User id=" + ODBC_USR + "Password=" + PWD
using (SqlConnection connection = new SqlConnection(myConnectionString))
{
string mySelectQuery = #"SELECT a,b,c,d,e,f,g,h,i,...
FROM package p
JOIN package_download pd on p.package_id = pd.package_id
join download d on pd.download_id = d.download_id
WHERE p.package_name = #PackageName
AND ds.server_address LIKE 'tcp/ip%'
ORDER by a,b,c,d";
try
{
connection.Open();
using (SqlDataAdapter da = new SqlDataAdapter(mySelectQuery, connection))
{
using (SqlCommand cmd = new SqlCommand())
{
da.SelectCommand.Parameters.AddWithValue("#PackageName", txtPackage.Text);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count>0) // Make sure there is something in your DataTable
{
String aVal = dt[0]["a"].ToString();
String bVal = dt[0]["b"].ToString();
// You'll be the one to fill up
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I change your LIKE 'tcp/ip' to LIKE 'tcp/ip%' by the way which is the more appropriate one of using LIKE.
you can use ado.net entity data table to reference the tables in your sql server. I don't know if you're asking exactly this but it may help. because direct referencing to sql server is not possible as far as i know.

Updating through SqlDataAdapter and DataSet in C#

I have the fol code
string user = "new user";
DataSet myDS = new DataSet();
string sql = string.Format("Select Counter,Occupants From Rooms where Room = '{0}'",room);
SqlDataAdapter dAdapt = new SqlDataAdapter(sql, cnn);
dAdapt.Fill(myDS, "Rooms");
foreach (DataTable dt in myDS.Tables)
{
int var =(int) dt.Rows[0].ItemArray[0];
var--;
dt.Rows[0].ItemArray[0] = var;
String occups = dt.Rows[0].ItemArray[1].ToString();
occups += user;
dt.Rows[0].ItemArray[1] = occups;
}
dAdapt.Update(myDS,"Rooms");
I'm retrieving a single row with two columns-- Counter(small int type) and Occupants(text type). I get an error saying that the data types text and var char are incompatible in the equal to operator But the error is pointed to the line dAdapt.Fill(myDS, "Rooms"); which is weird. What's wrong here? And I'm pretty sure that the db connection is open as I've checked it by printing the connection status.
This won't work anyway unless you have specified an Update-Command for the DataAdaper.
I would not load the record into memory to update it. Meanwhile it could have been changed from another transaction. It's inefficient anyway. Instead i would use a single update-command:
string updateSql = #"
UPDATE ROOMS SET
Counter = Counter + 1,
Occupants = Occupants + ',' + #newUser
WHERE
Room = #Room";
using(var con = new SqlConnection(connectionString))
using (var updateCommand = new SqlCommand(updateSql, con))
{
updateCommand.Parameters.AddWithValue("#newUser", user);
updateCommand.Parameters.AddWithValue("#Room", room);
con.Open();
updateCommand.ExecuteNonQuery();
}
The problem is in your select, because you can use the syntax, that Room = 'something', because text is not compatible with =.
Use LIKE instead of equal sign (=).
Fixed query should look like:
SELECT Counter,Occupants FROM Rooms WHERE Room LIKE '{0}'
But I recommand to use SqlParameters instead of string.Format, because it is not secure.

Is there a built in class I can use to parse a string containing a MySQL column datatype and return an equivalent .NET Type object?

Is there a built in class I can use to parse a string containing a MySQL column datatype and return an equivalent .NET Type object?
I want to convert some code that reads the column information from a table so that instead of having to pull back a row of data and getting the Schema information from that (using OdbcDataAdapter.FillSchema) - instead the method issues a command that does not do a table scan (hopefully quicker) to get the same info.
Existing code to be replaced:
QueryStr.Append("SELECT * FROM ")
.Append("`" + tableName + "`")
.Append(" LIMIT 1 ");
DataTable dsTable = new DataTable();
using (OdbcConnection DbConn = new OdbcConnection(ConnectionStr))
{
OdbcDataAdapter cmd = new OdbcDataAdapter(QueryStr.ToString(), DbConn);
try
{
cmd.FillSchema(dsTable, SchemaType.Mapped);
QuerySuccessful = true;
}
Attempt at new code:
StringBuilder QueryStr = new StringBuilder();
QueryStr.Append("DESCRIBE ")
.Append("`" + tableName + "`");
DataTable dsTable = new DataTable();
try
{
using (OdbcConnection DbConn = new OdbcConnection(connectionStr))
{
DbConn.Open();
OdbcCommand cmd = new OdbcCommand(QueryStr.ToString(), DbConn);
OdbcDataReader odrColumnReader = cmd.ExecuteReader();
while (odrColumnReader.Read())
{
string strColumnName = odrColumnReader.GetString(0);
string strColumnType = odrColumnReader.GetString(1);
// strColumnType is a string containing the type - e.g. char(6) or whatever
Type type = typeof (string); // TODO replace this bit with a conversion of strColumnType
columns.Add( new SQLcolumn(strColumnName, type, tableName));
}
DbConn.Close();
}
}
The trouble with this is that I get back strColumnType as a string - I want to convert it to a .NET type to match what I got back from FillSchema.
I'd prefer not to code my own conversion method [using this info http://msdn.microsoft.com/en-us/library/cc668763.aspx ] if one exists in the FrameWork / ODBC / ADO.NET.
You can use the OdbcDataReader.GetFieldType method, eg:
Type firstColumnType = odrColumnReader.GetFieldType(0);

How to get the SqlType of a column in a DataTable?

I have a DataTable obtained from a SQL DataBase, like this:
using (SqlCommand cmd = new SqlCommand(query, _sqlserverDB))
{
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataSet dataSet = new DataSet();
adapter.Fill(dataSet);
result = (dataSet != null && dataSet.Tables != null && dataSet.Tables.Count > 0) ? dataSet.Tables[0] : null;
}
}
When I try to get the DataType of each column through dataColumn.DataType , I get the C# types (Int32, Int64, String, etc).
QUESTION: How can I access the native SQL data types (varchar, nvarchar, bigint...) instead of the C# types?
I have tried dataColumn.DataType.UnderlyingSystemType and the result is the same.
Of course it is possible to take SqlDbType of a column, the answer is here on SO: link.
SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = "SET FMTONLY ON; select column from table; SET FMTONLY OFF";
SqlDataReader reader = cmd.ExecuteReader();
SqlDbType type = (SqlDbType)(int)reader.GetSchemaTable().Rows[0]["ProviderType"];
You cannot because System.Data.DataTable (or DataColumn, or DataSet, or DataRow...) is a generic .NET data container which works the same way regardless on the specific database engine you loaded your data from.
this means that provided you used a .NET Connector for SQL Server, MySQL, Access, PostgreSQL or anything else, the DataTable and DataColumn classes are always the same and being ADO.NET objects are generic to work with any db engine, so the columns are typed with the .NET types as you have found out.
SqlConnection SqlCon = new SqlConnection("Data Source=(local);Database=dbname;Integrated Security=SSPI;");
SqlCon.Open();
SqlCmd = SqlCon.CreateCommand();
SqlCmd.CommandText = "select * from Tablename";
SqlDataReader SqlDr = SqlCmd.ExecuteReader();
SqlDr.Read();
int i = 0;
while (i < SqlDr.FieldCount)
{
MessageBox.Show(SqlDr.GetDataTypeName(i));
i++;
}
Another approach is to let SQL do the work for you:
SqlConnection rConn = connectToSQL(); //returns sql connection
SqlCommand SqlCmd = new SqlCommand();
SqlCmd = rConn.CreateCommand();
SqlCmd.CommandText = "SELECT ORDINAL_POSITION, " +
"COLUMN_NAME, " +
"DATA_TYPE, " +
"CHARACTER_MAXIMUM_LENGTH, " +
"IS_NULLABLE " +
"FROM INFORMATION_SCHEMA.COLUMNS " +
"WHERE TABLE_NAME = 'TableName'";
SqlDataReader SqlDr = SqlCmd.ExecuteReader();
SqlDr.Read();
while (SqlDr.Read()) {
var OrdPos = SqlDr.GetValue(0);
var ColName = SqlDr.GetValue(1);
var DataType = SqlDr.GetValue(2);
var CharMaxLen = SqlDr.GetValue(3);
var IsNullable = SqlDr.GetValue(4);
Console.WriteLine("ColName - " + ColName + " DataType - " + DataType + " CharMaxLen - " + CharMaxLen);
}
As David says ... you are in .NET so the types will be .NET types. This is a listing of type mappings from SQL Server to .Net that shows you what .NET type you will end up with for a given Sql column type .. hope this helps ..
http://msdn.microsoft.com/en-us/library/ms131092.aspx
Building upon Madhukar Krishna's answer, if you have a SQLDataReader or a MySQLDataReader object you can obtain the SQL type metadata for a given column (in the code, we obtain the metadata of column with index 1) using the following code (example working for MySQLDataReader object):
...
MySqlDataReader dr = ...
Console.WriteLine("dr.GetFieldType(1) = {0}, dr.GetName(1) = {1}, dr.GetValue(1) = {2}, dr.GetDataTypeName(1) = {3}",
dr.GetFieldType(1), dr.GetName(1), dr.GetValue(1), dr.GetDataTypeName(1));
bool b = Enum.TryParse(dr.GetDataTypeName(1), true, out System.Data.SqlDbType mySqlDbTypeEnum);
Console.WriteLine("mySqlDbTypeEnum = {0}, b = {1}", mySqlDbTypeEnum, b);
The line:
bool b = Enum.TryParse(dr.GetDataTypeName(1), true, out System.Data.SqlDbType mySqlDbTypeEnum);
is used to obtain the System.Data.SqlDbType from a String, and ignoring the letter case, e.g. if dr.GetDataTypeName(1) returns "VARCHAR" then the System.Data.SqlDbType enum value is System.Data.SqlDbType.VarChar.
Then, you can get get the size of the data type (for instance VARCHAR(15)) by inspecting the SQL columns metadata with the following code (source MSDN):
... (continuation)
DataTable schemaTable;
// Retrieve column schema into a DataTable.
schemaTable = dr.GetSchemaTable();
// For each field in the table...
foreach (DataRow myField in schemaTable.Rows)
{
// For each property of the field...
foreach (DataColumn myProperty in schemaTable.Columns)
{
// Display the field name and value.
Console.WriteLine(myProperty.ColumnName + " = " + myField[myProperty].ToString());
}
Console.WriteLine();
// Pause.
//Console.ReadLine();
}
The property ColumnSize gives the size information.
If you are using DataReader -
SqlDataReader reader = cmd.ExecuteReader();
reader.GetDataTypeName(int ordinal)
should work if you want the SQL data type of a column

Categories

Resources