Initialise Table adapter manually - c#

How would I go about initialising a table adapter properly pragmatically? Normally, I would use the table adapter that get's created for me when I drag and drop the Data Table onto my form, but have never used one in a custom class before.
Cheers!
EDIT:
I think I need to explain my scenario in more detail.
I've added a method on my datatable inside my dataset. I want to be able to call this method from inside a custom class. Therefore I'd need a valid Table Adapter to be created to allow me to do this.

Just like this:
var dt = new DataTable();
using (SqlConnection c = new SqlConnection(cString))
using (SqlDataAdapter sda = new SqlDataAdapter("SELECT ...", c))
{
sda.SelectCommand.Parameters.AddWithValue("#field1", field1);
etc...
sda.Fill(dt);
}

void FillData()
{
// 1
// Open connection
using (SqlConnection c = new SqlConnection(
Properties.Settings.Default.DataConnectionString))
{
c.Open();
// 2
// Create new DataAdapter
using (SqlDataAdapter a = new SqlDataAdapter(
"SELECT * FROM EmployeeIDs", c))
{
// 3
// Use DataAdapter to fill DataTable
DataTable t = new DataTable();
a.Fill(t);
// 4
// Render data onto the screen
// dataGridView1.DataSource = t; // <-- From your designer
}
}
}
EDIT:
Why don't you make this method in a separate class that will be called in your data table and wherever else you will need to? You will just make an instance of the class and call the public method of that class.

Related

How to solve the "Connection Was Not Closed, The connections current state is open" in c#?

So I'm trying to practice c# and stumbled with the connection error, I already stated that my connection will be closed but it tells me that my connection is still open. I really have no idea what's wrong with this.
public void getdept()
{
con.Open();
string query = "SELECT * FROM positions where PositionName=" + cbxposname.SelectedValue.ToString() + "";
SqlCommand cmd = new SqlCommand(query, con);
DataTable dt = new DataTable();
SqlDataAdapter sda = new SqlDataAdapter(query, con);
sda.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
txtdeptname.Text = dr["Department"].ToString();
}
con.Close();
}
Any tips is welcomed!
You appear to be using a common connection object. Don't. Create your connection object where you use. Do so with a using statement and then the connection will be closed and destroyed at the end of the block. Store your connection string in a common location and then use that each time to create a new connection, e.g.
var table = new DataTable();
using (var connection = new SqlConnection(connectionString)
using (var adapter = new SqlDataAdapter("SQL query here", connection)
{
adapter.Fill(table);
}
// use table here.
There are a number of things to note from this code, other than the using block.
Firstly, it doesn't explicitly open the connection because there's no point. The Fill and Update methods of a data adapter will implicitly open the connection if it's currently closed and it will implicitly close the connection if it opened it. When using a data adapter, the only reason to open the connection explicitly is if you're calling multiple Fill and/or Update methods, so the connection is closed and reopened in between. Even if you do open the connection though, there's still no need to close it explicitly because that happens implicitly at the end of the using block.
Secondly, this code doesn't create a command object because there's no point. In your original code, you create a command object and then you don't use it. If you already have a command object then you can pass that to the data adapter constructor but you don't do that. You pass the SQL query and the connection, so the data adapter will create its own SelectCommand.
In actual fact, there's no point even creating a connection object here. The data adapter has a constructor that accepts a SQL query and a connection string, so you can just create the data adapter and let it do the rest internally:
var table = new DataTable();
using (var adapter = new SqlDataAdapter("SQL query here", connectionString)
{
adapter.Fill(table);
}
// use table here.
You are unnecessary opening and closing connections in your case. It's not needed here.
Your code should look like this.
using (SqlConnection con = new SqlConnection(connetionString))
{
using (DataTable dt = new DataTable())
{
using (SqlDataAdapter sda = new SqlDataAdapter(sql, con))
{
sda.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
txtdeptname.Text = dr["Department"].ToString();
}
}
}
}
A few suggestions also, Please don't use * in the query, instead, use column names, Please use NOLOCK in the Query if it's required in your case and use the parameterized query.

How to load the datagridview using OOP C#

I am a beginner at C# and .NET oop concepts. I want to load the datagridview. I don't know how to pass the data. What I tried so far I attached below.
I created a class std
public void get()
{
SqlConnection con = new SqlConnection("server =.; initial catalog=testdb; User ID=sa; Password=123");
string sql = "select * from std";
con.Open();
SqlCommand cm = new SqlCommand(sql, con);
SqlDataReader dr = cm.ExecuteReader();
while ( dr.Read())
{
string stname = dr["st_name"].ToString();
string nicnum = dr["nic"].ToString();
}
con.Close();
}
Form: I am getting data like this way
std ss = new std();
ss.get();
dataGridView1.Rows.Clear();
If I wrote like this way how to pass data into the datagridview columns? I am stuck in this area
It's easier like this:
public void FillGrid()
{
var dt = new DataTable();
var da = new SqlDataAdapter("select * from std", "server =.; initial catalog=testdb; User ID=sa; Password=123");
da.Fill(dt);
dataGridView1.DataSource = dt;
}
but if you're going to use such a low level method of database access you should consider adding a DataSet type of file to your project; visual studio will write all this code and more for you with a few mouse clicks, and it makes a good job of creating tables and adapters that are a lot easier to work with
you have made multiple mistakes. First you read data wirh dataraeader and in every iteration define two stname and nimnum variables like. So when loop ends variables are destroyed. You have to define data table and read data by dataraeader and and add them to it row by row. Or read by sqldataadapter and read it immediately and pass to datatable object.Finnaly you pass datatable as return object of function. Use this vala as datasource of datagridview property if I'm not wrong.

How to display results in DataGridView using a text box as the input to a SQL query with parameters

Using Visual Studio 2017, I'm trying to build a Windows Forms application that asks a user for specific value from a SQL Server Express database (footballteam).
User enters a value (#jnumber) in a text box (textBox1.Text) which corresponds to the "LIKE" for "JERSEYNUMBER".
Then, the query (commandText) is to be executed after clicking on button (button1_Click)
Results should display a DataGridView.
Build results were: "Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped".
However, when running the application, user enters a number value for #jnumber in textBox.Text, then clicks on button (button1_Click), but dataGridView1 remains empty; no results.
Goal is also to avoid SQL injection. Appreciate your help.
Code is here:
// directives
using System;
using System.Data
using System.Windows.Forms;
using System.Data.SqlClient;
namespace displaydmlquery
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// variable sql query
var commandText = "SELECT * FROM JERSEY WHERE JERSEYNUMBER LIKE '%' + #jnumber+ '%' ORDER BY ASSIGNMENT_DATE";
// variable connection string
var connectionString = "Server=hostname\\SQLEXPRESS;Database=footballteam;User Id=userid;Password=password";
// Create a connection instance
using (SqlConnection connection = new SqlConnection(connectionString))
{
// Create a SqlCommand instance
SqlCommand command = new SqlCommand(commandText, connection);
// Add the parameter to used in the text box input
command.Parameters.Add("#jnumber", SqlDbType.NVarChar, 20).Value = textBox1.Text;
// Execute query
try
{
// open connection
connection.Open();
// create a SqlDataAdapter to execute query
var dataAdapter = new SqlDataAdapter(commandText, connectionString);
// Create command builder
var commandBuilder = new SqlCommandBuilder(dataAdapter);
// Execute query reader
command.ExecuteReader();
// create a data table to hold query
DataTable dtRecord = new DataTable();
// fill in data tbale
sqlDataAdap.Fill(dtRecord);
// Display results in DataGridView
dataGridView1.DataSource = dtRecord;
}
catch
{
// Handle exception, future code
}
finally
{
connection.Close();
}
}
}
}
}
I was trying to hint at what your problems were in the comments but I failed so I'm taking the time to give you a complete answer.
Below is what your code is doing. You'll notice that some of the lines have question marks. These are the troubling lines because they don't make any sense. It seems you're confusing what the different data objects are meant to do.
1. set up a sql string
2. set up a connection string
3. create a connection Object from connection string from (2)
4. create a command Object from the sql string and the connection object from (1) and (3)
5. set the value of the parameter on the command object from (4)
6. open the connection Object from (3)
7. create a DataAdapter object and a new connection Object (???)
and a new command Object (???) from (1) and (3)
8. create commandBuilder and generate INSERT UPDATE and DELETE commands Objects (???) from the data adapter (7)
9. execute the command object from (4). Disregard the results (???)
10. create a new DataTable Object
11. fill the DataTable from (10) with an unknown sqlDataAdap (does it have
connection, sql, or parameters associated ????)
12. set the DataSource on the datagrid to the filled(?) datatable from (10)
13. throw away exceptions (???)
14. close the connection
15. dispose the connection
Here's some code that should work
using (SqlConnection connection = new SqlConnection(connectionString))
{
// Create a SqlCommand instance
SqlCommand command = new SqlCommand(commandText, connection);
// Add the parameter to used in the text box input
command.Parameters.Add("#jnumber", SqlDbType.NVarChar, 20).Value = textBox1.Text;
// open connection
connection.Open();
// create a SqlDataAdapter using the command object with the parameters set
var dataAdapter = new SqlDataAdapter(command, connectionString);
// create a data table to hold query
DataTable dtRecord = new DataTable();
// fill in data table with the dataAdapater
dataAdapter.Fill(dtRecord);
// Display results in DataGridView
dataGridView1.DataSource = dtRecord;
} // Using will close the connection when it disposes it
Please try with updating your query
// variable sql query
var commandText = "SELECT * FROM JERSEY WHERE JERSEYNUMBER LIKE '%' #jnumber '%' ORDER BY ASSIGNMENT_DATE";
and add parameter as you are already doing....

Exceptions: System.NullReferenceException while trying to create relation between tables in dataSet

using C#, .net framework 4.5, VS 2012
Try to create simple relation between tables in data set, but got System.NullReferenceException, as I can see on MSDN, it's mean occurs when you try to reference an object in your code that does not exist. But, think i create all required objects.
My code below:
//create place for storing all tables from data base
private DataSet myDS = new DataSet("AutoLot");
//command builders for easy way access to tables
private SqlCommandBuilder sqlCInventory;
private SqlCommandBuilder sqlCOrders;
private SqlCommandBuilder sqlCCustomers;
//adapters for each table
private SqlDataAdapter sqlAInventory;
private SqlDataAdapter sqlAOrders;
private SqlDataAdapter sqlACustomers;
//connection string
private string cnStr = string.Empty;
public MainForm()
{
InitializeComponent();
//get connection string from .config file
cnStr =
ConfigurationManager.ConnectionStrings["AutoLotSqlProvider"].ConnectionString;
//create adapters
sqlACustomers = new SqlDataAdapter("Select * From Customers", cnStr);
sqlAInventory = new SqlDataAdapter("Select * From Inventory", cnStr);
sqlAOrders = new SqlDataAdapter("Select * From Orders", cnStr);
//automatic generate commands
sqlCCustomers = new SqlCommandBuilder(sqlACustomers);
sqlCInventory = new SqlCommandBuilder(sqlAInventory);
sqlCOrders = new SqlCommandBuilder(sqlAOrders);
//add table to data Set
sqlAInventory.Fill(myDS);
sqlAOrders.Fill(myDS);
sqlACustomers.Fill(myDS);
//create relationship between tables
BuildTableRelationShip();
//create DataSourse for datGrids on UI
dataGridViewCustomer.DataSource = myDS.Tables["Inventory"];
dataGridViewOrders.DataSource = myDS.Tables["Orders"];
dataGridViewCustomer.DataSource = myDS.Tables["Customers"];
}
and here I got exception
private void BuildTableRelationShip()
{
//create object of relationShips
DataRelation dr = new DataRelation("CustomersOrders", //name of relation
myDS.Tables["Customers"].Columns["CustID"], //main columns
myDS.Tables["Orders"].Columns["OrderID"]); //related columns
myDS.Relations.Add(dr);
//second relation
dr = new DataRelation("InventoryOrder",
myDS.Tables["Inventory"].Columns["CarID"],
myDS.Tables["Orders"].Columns["OrderID"]);
//add relations to dataset
myDS.Relations.Add(dr);
}
Why i got this Null reference Exception? What i miss?
EDIT
You should call fill on individual DataTables rather than the whole DataSet.
sqlAInventory.Fill(myDS);
sqlAOrders.Fill(myDS);
sqlACustomers.Fill(myDS);
would become
sqlAInventory.Fill(myDS, "Inventory");
sqlAOrders.Fill(myDS, "Orders");
sqlACustomers.Fill(myDS, "Customers");
This method will automatically add a table to your DataSet if it doesn't exist, and populates it with data if it does. MSDN has more information on this method of the fill.

WinForms DataGridView - update database

I know this is a basic function of the DataGridView, but for some reason, I just can't get it to work. I just want the DataGridView on my Windows form to submit any changes made to it to the database when the user clicks the "Save" button.
I populate the DataGridView according to a function triggered by a user selection in a DropDownList as follows:
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
SqlDataAdapter ruleTableDA = new SqlDataAdapter("SELECT rule.fldFluteType AS [Flute], rule.fldKnife AS [Knife], rule.fldScore AS [Score], rule.fldLowKnife AS [Low Knife], rule.fldMatrixScore AS [Matrix Score], rule.fldMatrix AS [Matrix] FROM dbo.tblRuleTypes rule WHERE rule.fldMachine_ID = '1003'", con);
DataSet ruleTableDS = new DataSet();
ruleTableDA.Fill(ruleTableDS);
RuleTable.DataSource = ruleTableDS.Tables[0];
}
In my save function, I basically have the following (I've trimmed out some of the code around it to get to the point):
using (SqlDataAdapter ruleTableDA = new SqlDataAdapter("SELECT rule.fldFluteType AS [Flute], rule.fldKnife AS [Knife],
rule.fldScore AS [Score], rule.fldLowKnife AS [Low Knife],
rule.fldMatrixScore AS [Matrix Score], rule.fldMatrix AS [Matrix]
FROM dbo.tblRuleTypes rule WHERE rule.fldMachine_ID = '1003'", con))
{
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(ruleTableDA);
DataTable dt = new DataTable();
dt = RuleTable.DataSource as DataTable;
ruleTableDA.Fill(dt);
ruleTableDA.Update(dt);
}
Okay, so I edited the code to do the following: build the commands, create a DataTable based on the DataGridView (RuleTable), fill the DataAdapter with the DataTable, and update the database. Now ruleTableDA.Update(dt) is throwing the exception "Concurrency violation: the UpdateCommand affected 0 of the expected 1 records."
I believe there are a few problems here:
The sequence to keep in mind is that when you load up your grid, it is pointed to a datatable/set already.
When you type into the grid, the changes are temporarily persisted to the data table that is bound to the grid. Therefore, you do not want to be creating a data table every time you save, because the changes that were made to the existing data table are being ignored.
Second issue is that you probably don't need to create a binding source everytime, because just like the first point, if the grid is showing data, there is already a binding source that it is bound to.
Third problem is that the SQLCommandBuilder class has methods like GetInsertCommand, GetUpdateCommand, etc. that must be used to actually get the appropriate commands.
using (SqlDataAdapter ruleTableDA = new SqlDataAdapter("SELECT rule.fldFluteType AS [Flute], rule.fldKnife AS [Knife],
rule.fldScore AS [Score], rule.fldLowKnife AS [Low Knife],
rule.fldMatrixScore AS [Matrix Score], rule.fldMatrix AS [Matrix]
FROM dbo.tblRuleTypes rule WHERE rule.fldMachine_ID = '1003'", con))
{
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(ruleTableDA);
DataTable dt = new DataTable();
dt = RuleTable.DataSource as DataTable;
//ruleTableDA.Fill(dt);
ruleTableDA.Update(dt);
}
MSDN documentation states that the update/delete/insert commands are automatically set when you manually set the SelectCommand. It doesn't mention that it does the same when you construct one with a SqlDataAdapter. Try adding these lines after creating your SqlCommanduBuilder.
ruleTableDA.UpdateCommand = commandBuilder.GetUpdateCommand()
ruleTableDA.InsertCommand = commandBuilder.GetInsertCommand()
ruleTableDA.DeleteCommand = commandBuilder.GetDeleteCommand()
You may need this to get the Update Command
ruleTableDA.UpdateCommand = commandBuilder.GetUpdateCommand();

Categories