Referencing a control from SQL query - c#

I'm using C# to link with an Access database I have. I added this database by using the Data Source Configuration Wizard in VS, and now there are a couple of queries I'm trying to run.
This is the query I'm having trouble with, I think it's having an issue with me trying to reference a combobox from inside the query.
SELECT DISTINCT Column2
FROM MyTable
WHERE Column1 = cboMyComboBox.Text
ORDER BY Column2
A sample of data in the MyTable
Column1 Column2
Male Bob
Female Jane
Male Jim
Male John
Female Jill
And lets say the value in cboMyComboBox is 'Male'
I'm trying to get the query to return 'Bob', 'Jim' and 'John'
I'm pretty new to this so I'm probably missing something completely obvious, and feel free to refer me to any guides on doing this properly. (It may have something to do with parameters...? Do i need to be passing something to this query?)
The error I'm receiving is "No value given for one or more required parameters"

string query = String.Format(
#"SELECT DISTINCT Column2 FROM MyTable
WHERE Column1 = '{0}' ORDER Y Column2", cboMyComboBox.Text);
Otherwise the sql query will try and literally match column1 to the string cboMyComboBox.Text as opposed to the data in it.
In complete form:
public DataTable dattab;
public void GetData()
{
//setup the parameters for connecting
string connString = #"";// You need to define you connection string here.
string query = String.Format(#"SELECT DISTINCT Column2 FROM MyTable WHERE Column1 = '{0}' ORDER Y Column2", cboMyComboBox.Text);
//Create the connection and commmand objects, then open a connection to the DB.
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
//Retrieve the data and fill the datatable
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dattab);
//Close off connections
conn.Close();
da.Dispose();
}

Figured it out - In the query properties there is an option to add parameters - I was able to add it here then pass the combobox value when i ran the query method:
tableAdapter.GetColumn1Data(cboMyComboBox.Text)

Related

how to select from a table in access with a string variable

I have a database in ms-access and wanted to select from it,
I know my question is very simple but I couldn't find the solution for it
this is how I want to select:
public static void SearchRationCreatorName(string RationCreator)
{
string StrCon = System.Configuration.ConfigurationManager....
OleDbConnection Connection = new OleDbConnection(StrCon);
OleDbDataAdapter DataA = new OleDbDataAdapter
("Select * from tRations where tRations.RationCreator= [RationCreator]", Connection);
DataTable Dtable = new DataTable();
DataA.Fill(Dtable);
but instead of selecting one row it select all of records in that table
That didn't show up well in the comment.
I think you mean
"Select * from tRations where RationCreator= '"+RationCreator+"'"
The way you worded your title suggests you may want to use a string in place of a tablename but your code suggests otherwise. IF you wanted to know how to select from a dynamic table, let me know.
Also, this will select all rows that match rationcreator. If you only want one row, use:
"Select TOP 1 * from tRations where RationCreator= '"+RationCreator+"'"
with or without an ORDER BY predicate

Writing information from SQL Server to C#

Below I have a piece of code that should be writing out columns from my database, however when I try to execute, it gives me an exception that says it can't read a column with no values, but its wrong because it should contain dates in the columns that I want information to come out of.
Here is the table definition:
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
PATRICK_DEV dbo FILE_DATE_PROCESSED BASE TABLE
Here is the code:
try
{
SqlConnection connect = new SqlConnection("Server=OMADB01;Database=PATRICK_DEV;Trusted_Connection=True;");
connect.Open();
SqlCommand command = new SqlCommand("INSERT FILE_DATE_PROCESSED(UID, FILE_DATE_PROCESSED, FILE_NAME, DATE_ENTERED) SELECT newid(), '2015-12-31 19:32:45', 'myfilename.txt', getdate()", connect);
SqlDataReader reader = null;
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader["FILE_DATE_PROCESSED"].ToString());
Console.WriteLine(reader["DATE_ENTERED"].ToString());
}
connect.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
This is what I am dealing with right now: I have a database in SQL that looks like this:
UID FILE_DATE_PROCESSED FILE_NAME DATE_ENTERED
In this database, every time I add a file, column 2 should contain the last time I entered the file, and column 4 should contain the time I am entering the file now. This is the result that I am looking for:
UID FILE_DATE_PROCESSED FILE_NAME DATE_ENTERED
random random date the file name the current date
number
If there is a different way of solving this problem than what I have posted please let me know I will very much appreciate it.
Your query executes an INSERT (IE. Adds data to your table) It doesn't retrive any record. The INSERT statement in T-SQL could use a SELECT subquery to feed the values that are requested by the columns listed after the INSERT.
So your query add a new record every time you run it, but there is no column returned from that query and using the reader indexer on a non existant column produces the mentioned error.
If you just want to read values then you should change your query to
try
{
using(SqlConnection connect = new SqlConnection(....))
using(SqlCommand command = new SqlCommand(
#"SELECT FILE_DATE_PROCESSED, DATE_ENTERED FROM FILE_DATE_PROCESSED", connect))
{
connect.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader["FILE_DATE_PROCESSED"].ToString());
Console.WriteLine(reader["DATE_ENTERED"].ToString());
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
I suggest also to change the column name FILE_DATE_PROCESSED or the table name because having two objects with the same name could be an endless source of confusion and an excellent error maker
You don't have a select statement. Changing to add a select statement with names might help:
#cmdText = #"DECLARE #FILE_DATE_PROCESSED DATETIME = '2015-12-31 19:32:45',
#DATE_ENTERED DATETIME =getdate()
INSERT FILE_DATE_PROCESSED(UID, FILE_DATE_PROCESSED, FILE_NAME, DATE_ENTERED)
SELECT newid(), #FILE_DATE_PROCESSED, 'myfilename.txt',#DATE_ENTERED
SELECT #FILE_DATE_PROCESSED AS FILE_DATE_PROCESSED, #DATE_ENTERED as DATE_ENTERED"
SqlCommand command = new SqlCommand(#cmdText)

How to display values into gridview from sql databese

In my database i have three tables. One For employs where i keep their names, ids, salary... In the second one named Project i keep id, location, name. in the third one named WorksOn i keep the id from employs and the id from project. In my Asp .Net web site in gridview i need to display the employee's name and the name of the project that he is working.
string connect =
WebConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
SqlConnection con = new SqlConnection(connect);
try
{
con.Open();
}
catch (Exception err)
{
string error = err.Message;
con.Close();
}
SqlCommand command = new SqlCommand();
command.Connection = con;
SqlDataReader reader;
command.CommandText = "SELECT * FROM WorksON ";
reader= command.ExecuteReader();
In data source in gridview if i choose to display the values from WorksOn table it shows the id from employs and the id from project but what i need is to show the names on the employs and project.
I know that i need to do something with dataset but i don't know who.
Your SQL command must JOIN the related tables. Something like:
SELECT * FROM WorksOn JOIN Employee on WorksOn.EmployeeId = Employee.Id
Note that you should not SELECT "*" (all columns). You should only SELECT those columns that are necessary to your data view for performance.
On your SQL command, you don't mention anything about Employs. You need to use a JOIN SQL command in order to get both the employee name and the company name.
And instead of using "SELECT * FROM...", consider using the columns name instead, because you're not trying to get all the columns display. And it will help us understand the name of the columns to further help you.
Use a JOIN query like this:
SELECT project.projectName, employee.Name
FROM (worksOn
INNER JOIN employee
ON (worksOn.employeeId = employee.employeeId))
INNER JOIN project
ON (project.projectId = employee.employeeId)
AND (worksOn.projectId = project.projectId)

inserting data into multiple tables using a web form

i would like to know what is the standard/best way of doing the following:
i have a form web app in asp.net and using C#
the user will enter data into the form and click INSERT and it will insert data into 4 different tables.
the fields are:
primarykey, animal, street, country
the form allows for multiple animals, multiple streets and multiple countries per primarykey. so when i have data like this:
[1],[rhino,cat,dog],[luigi st, paul st], [russia,israel]
i need it inserted into tables like this:
table1:
1,rhino
1,cat
1,dog
table2:
1,luigi st
1, paul st
table3:
1,russia
1,israel
questions
I'm at a total loss on how to do this. if i just had one table and one set of data per primary key i would just use the InsertQuery and do it this way, but since it is multiple tables i don't know how to do this??
what control(s) should i use in order to allow user to input multiple values? currently i am just using textboxes and thinking of separating the entries by semi colons, but that's probably not the right way.
I wanted to recommend that you take advantage of the new multirow insert statement in SQL 2008 so that you can just pass a sql statement like this:
INSERT INTO table1(id,animal_name) values (1,cat),(1,dog),(1,horse)...
To your SqlCommand but I don't know how to build a statement like that w/o risking being victim of a SQL Injection Attack.
Another alternative is to define data table types in your sql database:
And then construct a DataTable in C# that matches your datatable type definition:
DataTable t = new DataTable();
t.Columns.Add("id");
t.Columns.Add("animal_name");
foreach(var element in your animals_list)
{
DaraRow r = t.NewRow();
r.ItemArray = new object[] { element.id, element.animal_name };
t.Rows.Add(r);
}
// Assumes connection is an open SqlConnection.
using (connection)
{
// Define the INSERT-SELECT statement.
string sqlInsert = "INSERT INTO dbo.table1 (id, animal_name) SELECT nc.id, nc.animal_name FROM #animals AS nc;"
// Configure the command and parameter.
SqlCommand insertCommand = new SqlCommand(sqlInsert, connection);
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue("#animals", t);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.AnimalTable";
// Execute the command.
insertCommand.ExecuteNonQuery();
}
Read more here.
Or if you are familiar with Stored Procedures, same as previous suggestion but having the stored procedure receive the DataTable t as parameter.
If none of the above work for you, create a SqlTranscation from the Connection object and iterate through each row of each data set inserting the record in the appropriate table and finally commit the transaction. Example here.
Use Checkboxes on the front end. Have a service/repository to save the user data. Something like the following:
public void UpdateUserAnimals(Guid userId, string[] animals)
{
using (SqlConnection conn = new SqlConnection("connectionstring..."))
{
using (SqlCommand cmd = new SqlCommand("Insert Into UserAnimals(UserId, Animals) values (#UserId, #Animal)"))
{
conn.Open();
cmd.Parameters.AddWithValue("#UserId", userId);
foreach(string animal in animals)
{
cmd.Parameters.AddWithValue("#Animal", animal);
cmd.ExecuteNonQuery();
}
}
}
}
There are more complex solutions, but this is a simple one.

Using temporary table in c#

I read an excel sheet into a datagrid.From there , I have managed to read the grid's rows into a DataTable object.The DataTable object has data because when I make equal a grid's datasource to that table object , the grid is populated.
My Problem : I want to use the table object and manipulate its values using SQL server,(i.e. I want to store it as a temporary table and manipulate it using SQL queries from within C# code and , I want it to return a different result inte a grid.(I don't know how to work with temporary tables in C#)
Here's code to execute when clicking button....
SqlConnection conn = new SqlConnection("server = localhost;integrated security = SSPI");
//is connection string incorrect?
SqlCommand cmd = new SqlCommand();
//!!The method ConvertFPSheetDataTable Returns a DataTable object//
cmd.Parameters.AddWithValue("#table",ConvertFPSheetDataTable(12,false,fpSpread2_Sheet1));
//I am trying to create temporary table
//Here , I do a query
cmd.CommandText = "Select col1,col2,SUM(col7) From #table group by col1,col2 Drop #table";
SqlDataAdapter da = new SqlDataAdapter(cmd.CommandText,conn);
DataTable dt = new DataTable();
da.Fill(dt); ***// I get an error here 'Invalid object name '#table'.'***
fpDataSet_Sheet1.DataSource = dt;
//**NOTE:** fpDataSet_Sheet1 is the grid control
Change your temp table from #table to ##table in both places.
Using ## means a global temp table that stays around. You'll need to Drop it after you have completed your task.
Command = " Drop Table ##table"
Putting the data into a database will take time - since you already have it in memory, perhaps LINQ-to-Objects (with DataSetExtensions) is your friend? Replace <int> etc with the correct types...
var query = from row in table.Rows.Cast<DataRow>()
group row by new
{
Col1 = row.Field<int>(1),
Col2 = row.Field<int>(2)
} into grp
select new
{
Col1 = grp.Key.Col1,
Col2 = grp.Key.Col2,
SumCol7 = grp.Sum(x => x.Field<int>(7))
};
foreach (var item in query)
{
Console.WriteLine("{0},{1}: {2}",
item.Col1, item.Col2, item.SumCol7);
}
I don't think you can make a temp table in SQL the way you are thinking, since it only exists within the scope of the query/stored procedure that creates it.
If the spreadsheet is a standard format - meaning you know the columns and they are always the same, you would want to create a Table in SQL to put this file into. There is a very fast way to do this called SqlBulkCopy
// Load the reports in bulk
SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString);
// Map the columns
foreach(DataColumn col in dataTable.Columns)
bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
bulkCopy.DestinationTableName = "SQLTempTable";
bulkCopy.WriteToServer(dataTable);
But, if I'm understanding your problem correctly, you don't need to use SQL server to modify the data in the DataTable. You c an use the JET engine to grab the data for you.
// For CSV
connStr = string.Format("Provider=Microsoft.JET.OLEDB.4.0;Data Source={0};Extended Properties='Text;HDR=Yes;FMT=Delimited;IMEX=1'", Folder);
cmdStr = string.Format("SELECT * FROM [{0}]", FileName);
// For XLS
connStr = string.Format("Provider=Microsoft.JET.OLEDB.4.0;Data Source={0}{1};Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'", Folder, FileName);
cmdStr = "select * from [Sheet1$]";
OleDbConnection oConn = new OleDbConnection(connStr);
OleDbCommand cmd = new OleDbCommand(cmdStr, oConn);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
oConn.Open();
da.Fill(dataTable);
oConn.Close();
Also, in your code you ask if your connection string is correct. I don't think it is (but I could be wrong). If yours isn't working try this.
connectionString="Data Source=localhost\<instance>;database=<yourDataBase>;Integrated Security=SSPI" providerName="System.Data.SqlClient"
Pardon me, if I have not understood what you exactly want.
If you want to perform SQL query on excel sheet, you could do it directly.
Alternatively, you can use SQL Server to query excel (OPENROWSET or a function which I dont remember right away). Using this, you can join a sql server table with excel sheet
Marc's suggestion is one more way to look at it.
Perhaps you could use a DataView. You create that from a DataTable, which you already have.
dv = new DataView(dataTableName);
Then, you can filter (apply a SQL WHERE clause) or sort the data using the DataView's methods. You can also use Find to find a matching row, or FindRows to find all matching rows.
Some filters:
dv.RowFilter = "Country = 'USA'";
dv.RowFilter = "EmployeeID >5 AND Birthdate < #1/31/82#"
dv.RowFilter = "Description LIKE '*product*'"
dv.RowFilter = "employeeID IN (2,4,5)"
Sorting:
dv.Sort = "City"
Finding a row: Find the customer named "John Smith".
vals(0)= "John"
vals(1) = "Smith"
i = dv.Find(vals)
where i is the index of the row containing the customer.
Once you've applied these to the DataView, you can bind your grid to the DataView.
Change the command text from
Select col1,col2,SUM(col7) From #table group by col1,col2
to
Select col1,col2,SUM(col7) From ##table group by col1,col2

Categories

Resources