Add data to a table from database - c#

I am new to .net and C# and I want to perform update/delete. I am using e template which has a table. I want to get data from database and display in that table and then perform update.
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString);
SqlDataReader rd;
SqlCommand comand = new SqlCommand();
//open connection with database
connection.Open();
//query to select all users with the given username
comand.CommandText = "select * from artikulli ";
rd = comand.ExecuteReader();
if(rd.HasRows )
{
while (rd.Read())
{
Row1.Items.Add(rd[0].ToString());
}
}
connection.Close();
}
Row1 is the id of table row. I know that this is not the best way and it doesn't work.
I get this error:
CS0103: The name 'Row1' does not exist in the current context
My table row Row1 is declared as below:
<td id="Row1" style="width: 73px"> </td>

It's apparent, as you've admitted, you are new to C#, so there are a number of things to point out, as have been addressed in the comments.
HTML elements are not going to be visible to the code-behind without the runat="server" attribute. (This attribute is required for ASP elements.)
As marc_s pointed out, your database communication would currently produce a run-time error, as the SqlCommand was not given a connection.
At some point you must really familiarize yourself with the using statement.
To correct your code-behind, it should be more like the following:
protected void Page_Load(object sender, EventArgs e)
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString))
{
using (SqlCommand command = connection.CreateCommand())
{
//open connection with database
connection.Open();
//query to select all users with the given username
command.CommandText = "select * from artikulli ";
List<object> users = new List<object>();
using (SqlDataReader rd = command.ExecuteReader())
{
if (rd.HasRows)
{
while (rd.Read())
{
users.Add(rd[0].ToString());
}
}
}
myGridView.DataSource = users;
myGridView.DataBind();
}
}
}
Where myGridView is an instance of a GridView created in the aspx page. The list users should be a list of whatever class you want to create to show user data, which will determine how your GridView instance will be formatted.
Just to get you to the point where you can see your database query working at all you can instead do the following from your query result (though I definitely recommend implementing the GridView eventually):
System.Text.StringBuilder sb = new System.Text.StringBuilder();
using (SqlDataReader rd = command.ExecuteReader())
{
if (rd.HasRows)
{
while (rd.Read())
{
sb.Append(rd[0].ToString());
sb.Append("<br />");
}
}
}
Row1.InnerHtml = sb.ToString();
And you will have to change your Row1 to
<td id="Row1" style="width: 73px" runat="server"> </td>

Per the error, you'll need to bring your Row1 variable into scope
TableRow Row1 = new TableRow();
while (rd.Read())
{
Row1.Items.Add(rd[0].ToString());
Table1.Rows.Add(Row1);
}

Related

Need to delete data from an access database in c#

I need to delete certain data from an access database when a button is clicked and it keeps throwing an error relating to the executeNonquery(), I'm really new to this I would appreciate any help, here is my code
private void btnDelete_Click(object sender, EventArgs e)
{
OleDbConnection myDb = new OleDbConnection(connectionString + DBFile);
myDb.Open();
if (ComboBoxSelection.SelectedIndex == 0)
{
OleDbCommand command = new OleDbCommand();
command.Connection = myDb;
foreach (DataGridViewRow myRow in dataGridView1.SelectedRows)
{
string query = "DELETE FROM Clients WHERE ClientID = '{int.Parse(txtEdit.text)}'";
command.CommandText = query;
}
command.ExecuteNonQuery();
myDb.Close();
}
else if (ComboBoxSelection.SelectedIndex == 1)
{
OleDbCommand command = new OleDbCommand();
command.Connection = myDb;
foreach (DataGridViewRow myRow in dataGridView1.SelectedRows)
{
string query = "DELETE FROM Clients WHERE ClientID = '{txtEdit.text}'";
command.CommandText = query;
}
command.ExecuteNonQuery();
myDb.Close();
}
}
Making a lot of assumptions about what you are trying to do, which is delete from the database every client id in the selected rows. This is a big assumption since you are using the same TextBox in your sample code for each row but I'm guessing this is a work in progress and you were going to get there eventually.
First, commands and connections are disposable resources so you should make sure they are Disposed when you are done with them. A common way to do that is to instantiate them in using blocks as I show below.
Second, you should always use parameterized queries, never concatenate strings together. I don't know if ClientID is a string or a number, you appear to use it both ways, but if someone typed ' OR 1=1; -- into the text box while the combobox was on index 1 then you could end up with everything deleted.
Lastly, you have a lot of duplication. Based on my assumptions, you can clean up your code to this:
private void btnDelete_Click(object sender, EventArgs e)
{
string query = "DELETE FROM Clients WHERE ClientID = #ClientID";
using (OleDbConnection myDb = new OleDbConnection(connectionString + DBFile))
using (OleDbCommand command = myDb.CreateCommand())
{
int clientid = 0;
command.CommandText = query;
OleDbParameter parClientID = new OleDbParameter("#ClientID", OleDbType.Integer);
command.Parameters.Add(parClientID);
myDb.Open();
foreach (DataGridViewRow myRow in dataGridView1.SelectedRows)
{
//Assume your client id is in a cell of the row? Zero for first, One for second, etc.
if (int.TryParse(myRow.Cells[0].ToString(), out clientid))
{
parClientID.Value = clientid;
command.ExecuteNonQuery();
}
}
}
}

how to populate textbox with new Row ID in windows form

I'm creating a windows form and currently in the process of creating the "create member" form.
Now i wish to show to the user inputting data what the new members ID will be. So i thought of trying to show the new row ID within a text box. So if we take the example below, when the form loads, the new member ID should be shown in the textbox
I've tried to attempt it below but having difficulty getting the result from the sqlCommand. Or maybe im going the wrong way around doing it ha
Can anyone see how i can apply the id upon load?
private void frmAddMember_Load(object sender, EventArgs e)
{
using (var connection = new SqlConnection(Properties.Settings.Default.BioEngineeringDB))
{
connection.Open();
using (var cmd = new SqlCommand("SELECT * FROM Users WHERE UserID=(SELECT MAX(UserID) FROM Users", connection))
{
//cmd.Parameters.Add("#MYVALUE", SqlDbType.VarChar).Value = comboBox1.Text;
SqlDataReader re = cmd.ExecuteReader();
if (re.Read())
{
txtMemberId.Text = // result from the SQLCommand but i dont know how to get it
You can access current row cells by indexing DataReader with columns names, like this txtMemberId.Text = thisReader["UserID"]; //here you should do increment. But honestly, generating Id in select max(id) + 1 manner is odd, GUIDs nad Autoinc integer is more commonly used in our days.
Your MAX+1 should looks like:
private void frmAddMember_Load(object sender, EventArgs e)
{
using (var connection = new SqlConnection(Properties.Settings.Default.BioEngineeringDB))
{
connection.Open();
using (var cmd = new SqlCommand("SELECT (COALESCE(MAX(UserID), 0) + 1) as UserID FROM Users", connection))
{
SqlDataReader re = cmd.ExecuteReader();
if (re.Read())
{
txtMemberId.Text = re["UserID"].ToString();
remove your autoinc id column and add a guid id col instead. then you can generate the Id on the client with Guid.NewGuid().ToString()
Assuming your ID column is being generated by the database (auto increment, etc...) just get the ID when you create the record.
var cmd = new SqlCommand("INSERT INTO User(FirstName) VALUES('bob')");
var id = (int) cmd.ExecuteScalar();
txtMemberId.Text = id.ToString();

How to check for domain Constraints using oleDb?

I have to find every columns that doesn't have a domain constraints in a database(MS Access) and for each one calculate min and max values to the current data and then to add from my program the corresponding constraint.
For example, a column "Foo" has the min value 0 and the max value 100,and I need the constraint "Foo between 0 And 100".
How can I check if a column has this constraint in C# ?
In access I found this at "Validation rules".
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
namespace Proiect
{
public partial class Form1 : Form
{
private OleDbConnection con = new OleDbConnection();
private new OleDbCommand cmd = new OleDbCommand();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'dataSet1.Carti'
this.cartiTableAdapter.Fill(this.dataSet1.Carti);
cartiTableAdapter.Fill(dataSet1.Carti);
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.ReadOnly = true;
con.ConnectionString="Provider=Microsoft.ACE.OLEDB.12.0;"+
"DataSource=D:\..\BD.accdb";
cmd.Connection=con;
this.cartiTableAdapter.Fill(this.dataSet1.Carti);
chkC.Checked=false;
}
private void chkC_CheckedChanged(object sender, EventArgs e)
{
}
}
}
For the purpose of checking the constrains applied on your table you are looking to use OleDbSchemaGuid.Check_Constraints Field. How to use this is actually a little bit different with how you would use per say OleDbSchemaGuid.Tables.
To help you on this I have written you a little console application that you can simply copy/paste on a new console application project in Visual Studio (or any preferred software) and run it to see how this works in action. The example is implemented on the famous Northwind database.
OleDbConnection cn = new OleDbConnection();
OleDbCommand cmd = new OleDbCommand();
//Open a connection to the SQL Server Northwind database.
// This is the sample DB I have used in my example.
cn.ConnectionString = "Provider=SQLOLEDB;Data Source=SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;";
cn.Open();
//Retrieve records from the Employees table into a DataReader.
cmd.Connection = cn;
cmd.CommandText = "SELECT * FROM Employees";
//Retrieve column schema into a constraints.
var schemaTable = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Check_Constraints,null);
//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.WriteLine("Done");
Console.ReadLine();
//Always close the DataReader and connection.
cn.Close();
and if you look at the output, you can see the constraint applied on the Discount field of Discount table.
CONSTRAINT_CATALOG = Northwind
CONSTRAINT_SCHEMA = dbo
CONSTRAINT_NAME = CK_Discount
CHECK_CLAUSE = ([Discount]>=(0) AND [Discount]<=(1))
DESCRIPTION =
Update
Also in general I will recommend you to get yourself familiar with How To Retrieve Column Schema by Using the DataReader GetSchemaTable Method and Visual C# .NET
The example below is the line by line copy of the code from link above except I have added a List of string to this code and captured the table's field name (called ColumnName in C# DataColumn in this context), and I have marked the lines I have added with // ++ Added ++.
OleDbConnection cn = new OleDbConnection();
OleDbCommand cmd = new OleDbCommand();
DataTable schemaTable;
OleDbDataReader myReader;
//Open a connection to the SQL Server Northwind database.
cn.ConnectionString = "Provider=SQLOLEDB;Data Source=EINSTEINIUM\\SQL2014EXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;Encrypt=False;TrustServerCertificate=False";
cn.Open();
//Retrieve records from the Employees table into a DataReader.
cmd.Connection = cn;
cmd.CommandText = "SELECT * FROM Employees";
myReader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
//Retrieve column schema into a DataTable.
schemaTable = myReader.GetSchemaTable();
// ++ Added ++
var listOfTableFields = new List<string>();
//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());
// ++ Added ++
if (myProperty.ColumnName == "ColumnName")
{
listOfTableFields.Add(myField[myProperty].ToString());
}
}
Console.WriteLine();
//Pause.
}
//Always close the DataReader and connection.
myReader.Close();
cn.Close();
// ++ Added ++
Console.WriteLine("List of fields in Employees table.");
// List of Fields in the Employees table.
foreach (var fieldName in listOfTableFields)
{
Console.WriteLine(fieldName);
}
Console.ReadLine();
Paste this code in a Console app and learn how to use it. It will be very easy then to move the parts you need to the buttons OnClick.

Insert into ListBox from a Database

Question: How can I insert items into a listbox from a database?
Here is what I tried:
public void Fetch()
{
using (SqlConnection cn = new SqlConnection(UtilObj.ConnectionString()))
{
cn.Open();
ExecuteFetch(cn);
cn.Close();
}
}
public void ExecuteFetch(SqlConnection cn)
{
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "spName";
cm.Parameters.AddWithValue("#Param1", Param1Val);
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
while (dr.Read())
{
myListBox.Items.Add(dr["Color"].ToString());
}
}
}
}
This shows an empty list when I run the code even though it populates in debugger.
ASPX Page
<asp:ListBox ID="myListBox" runat="server" />
I think you're looking for something like this:-
Get reader object after executing your sp
SqlDataReader reader = cmd.ExecuteReader();
myListBox.DataSource= reader; //reader object
myListBox.DataTextField = "Color"; // the field you want to show in listbox
myListBox.DataValueField = "Color"; // the value filed behind the items.
myListBox.Databind();
Text and Value Fields can be same as well if you want it that way
That's it. It's the same way you bind items to a dropdown list. Just used this in our recent project
Hope it's helpful

How to pass modified table name in SQL connection in ASP

I'm using SQL Server 2008 as my database in asp.net. And I'm passing the table name while at the time of clicking the <a> tag to web form. So how can I achieve this thing that when I click any link it change its sql query according to the value it receive?
For example:
<li class="last">
Item 1.1
</li>
Here cat contains the table name and sub contains the condition name.
And at the other side I'm doing:
SqlConnection con=new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag");
SqlDataAdapter da;
DataSet ds=new DataSet();
static DataTable dt = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
string s = Request.QueryString["cat"];
string s1 = Request.QueryString["sub"];
da = new SqlDataAdapter("select * from Architect where subcategory3='" + s1 + "'",con);
da.Fill(ds,"tab");
dt = ds.Tables["tab"];
DataGrid1.DataSource = dt;
DataGrid1.DataBind();
}
}
So I just want that insted of giving table name Architect I just want to pass s - how can I do that?
I would suggest that you think of other solution for this because what you are currently doing will lead to a very simple SQL Injection and your database will be at a great risk. I suggest that you have an enum of all tables and pass the id of the table in the query string instead of the table name and also you should make sure that the condition string is valid from any sql injection before making the string concatination
Your design isn't really optimal; is it possible to consider storing all data in a central table linked to both Category and SubCategory?
There are several weaknesses; any string concatenation of sql leaves you open to SqlInjection attacks. Even if you are choosing values from drop down lists, for example, it is still possible for client side script to modify the values in your combo boxes, or for an attacker to simply post data to your server side event handler.
In addition, having to source data from several tables means that you may have to deal with different schemas in your results; if you expect this (i.e. some tables will have more columns than others) then you can handle it appropriately.
Your query would then become something similar to:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
string s = Request.QueryString["cat"];
string s1 = Request.QueryString["sub"];
if(String.IsNullOrEmpty(s) || String.IsNullOrEmpty(s1)) { return; } //Improve Validation and error reporting
using(SqlConnection conn = new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag"))
{
using(SqlCommand command = new SqlCommand(conn))
{
command.CommandType = CommandType.Text;
command.CommandText = "SELECT * FROM Table WHERE Category = #Category AND SubCategory = #SubCategory";
command.Parameters.Add(new SqlParameter() { Type = SqlDbType.String, Name = "#Category", Value = s });
command.Parameters.Add(new SqlParameter() { Type = SqlDbType.String, Name = "#SubCategory", Value = s1 });
conn.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
DataTable data = new DataTable("MyData");
data.Load(reader);
DataGrid1.DataSource = data;
DataGrid1.DataBind();
}
}
}
}
}
If you are stuck with your original model, then you may want to whitelist the table names so you can stick with parameterised queries:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
string s = Request.QueryString["cat"];
string s1 = Request.QueryString["sub"];
if(String.IsNullOrEmpty(s) || String.IsNullOrEmpty(s1)) { return; } //Improve Validation and error reporting
using(SqlConnection conn = new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag"))
{
using(SqlCommand command = new SqlCommand(conn))
{
command.CommandType = CommandType.Text;
switch(s)
{
case "Architect":
command.CommandText = "SELECT * FROM Architect WHERE SubCategory = #SubCategory";
break;
case "SomethingElse":
command.CommandText = "SELECT * FROM SomethingElse WHERE SubCategory = #SubCategory";
break;
default:
return; //Again, improve error handling
}
command.Parameters.Add(new SqlParameter() { Type = SqlDbType.String, Name = "#SubCategory", Value = s1 });
conn.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
DataTable data = new DataTable("MyData");
data.Load(reader);
DataGrid1.DataSource = data;
DataGrid1.DataBind();
}
}
}
}
}
One comment I would make though, is that even if you implement either of the examples above, you still have a big problem; your data access code, business logic, and presentation code are all now munged into the code behind for this page. You will have to repeat this everywhere you need it leading to plenty of duplication, which is especially a problem when you need to fix bugs.
Instead, you might consider creating classes or using an ORM to handle all of this work for you, so you instead request a list of Architect objects, or a list of SomethingElse from a class or component, thus leaving the aspx to deal with the presentation. There is also a discussion here about why you might not want to use an ORM.
If you follow this route, your code might then become something like:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
string s = Request.QueryString["cat"];
string s1 = Request.QueryString["sub"];
//Still do validation on s and s1
ObjectFactory of = new ObjjectFactory();
DataGrid1.DataSource = ObjectFactory.GetObjects(s, s1);
DataGrid1.DataBind();
}
}
Effectively, it is now someone else's job to worry about how to get the objects, and to collect them, vastly reducing the code you have in your code behind. Plus you can easily reuse that across a wide variety of interfaces!
da = new SqlDataAdapter("select * from " + s + " where subcategory3='" + s1 + "'",con);
Like this ?
SqlConnection con=new SqlConnection("Data Source=ANURAG-PC;Initial Catalog=dbPortal;Persist Security Info=True;User ID=sa;Password=anurag");
SqlDataAdapter da;
DataSet ds=new DataSet();
static DataTable dt=new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
string s = Request.QueryString["cat"];
string s1 = Request.QueryString["sub"];
da = new SqlDataAdapter("select * from '"+s+"' where subcategory3='" + s1 + "'",con);
da.Fill(ds);
dt = ds.Tables[0];
DataGrid1.DataSource = dt;
DataGrid1.DataBind();
}
}

Categories

Resources