Best Practice code and issues - c#

I am a beginner and writing code to display data in a Gridview using Asp.Net and c#. I want to know if the approach I followed is correct or not. I want suggestions on standards and architectural issues, best practices with my code so that I can modify my code accordingly. I appreciate your great suggestions and code additions.
Connection Code:
public class DemoProjConnectionClass
{
public SqlConnection DemoProjConnection()
{
SqlConnection con = new SqlConnection("Data Source=Localhost;Initial Catalog=master;Integrated Security=True");
return con;
}
}
Domain Code(gets & sets):
public class DemoProjDomainClass
{
public int EmpId { get; set; }
public string EmpName { get; set; }
public int Salary { get; set; }
}
Class Library Code:
public class DemoProjServiceClass
{
public IList<DemoProjDomainClass> getDemoProjList()
{
string sqlDemoProjList;
sqlDemoProjList = "SELECT EmpId,EmpName,Salary from Employee";
DemoProjConnectionClass x = new DemoProjConnectionClass();
SqlConnection con = x.DemoProjConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sqlDemoProjList, con);
cmd.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds, "tempTable1");
IList<DemoProjDomainClass> DemoProjList = new List<DemoProjDomainClass>();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
DemoProjDomainClass _obj = new DemoProjDomainClass();
_obj.EmpId = Convert.ToInt16(ds.Tables[0].Rows[i][0]);_obj.EmpName = ds.Tables[0].Rows[i][1].ToString();_obj.Salary = Convert.ToInt16(ds.Tables[0].Rows[i][2]);DemoProjList.Add(_obj);
}
return DemoProjList;
}
}
UI Code
protected void Page_Load(object sender, EventArgs e)
{
DemoProjServiceClass ob=new DemoProjServiceClass();
GridView1.DataSource = ob.getDemoProjList();
GridView1.DataBind();
}

I suggest you to :
Use MVC instead asp.net classic
Use linq or EntityFramework instead (cmd,conn,adapter,dataset)
Use repeater instead grid for more performance
Take a look at this tutorial on asp.net site

Connection Code:
I will not hardcode the connectionstring like that. I will keep that in a config file (web.config or so..) and read from there so that i can change my connection string any time if needed with a recompilation.
Class Library Code
Your getDemoProjList method dont have any exception handling. I will wrap that code with using statement so that i dont need to worry abour closing my connection
UI
I dont think you should load data in the PageLoad without checking whether it is a postback or not. So will use a isPostBAck property checkk. I would also do a null check before binding it as the data source of the grid.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DemoProjServiceClass ob=new DemoProjServiceClass();
List<DemoProjDomainClass> objList=ob.getDemoProjList();
if(objList!=null)
{
GridView1.DataSource = objList;
GridView1.DataBind();
}
}
}

Not really.
What you need from this standpoint is data access layer.
http://martinfowler.com/eaaCatalog/
Use Data Source Architectural Patterns item.
Regarding your code connection most of time should not be hardcoded but defined in some kind of configuration file.
Let's assume Domain is fine, but most of time you need to implement Domain pattern which is described more in catalog as well if you have some additional logic of your domain models.
Avoid hardcoding of your sql queries due to possible SQL injection, use Disposable pattern ("using" keyword in terms of C# development) where appropriate. For major cases ORMs work pretty fine to accomplish basic functionality and even more, so there are only one two good reasons to use SqlCommand:
when you gain maximum performance or when you learn the basics. There cons as well. You maintainability decreases and amount of code increases.
From my prospective ASP.Net MVC provides you with highly maintainable and configurable level of code. That's why you can really pay some attention to it. But it's up to you if to do so or not.

For your Connection Code move everything inside of the SqlConnection brackets into your webconfig like this:
<connectionStrings>
<add name="abcConnectionString" connectionString="Data Source=Localhost;Initial Catalog=master;Integrated Security=True providerName="System.Data.SqlClient" />
</connectionStrings>
and then reference it in your code like this:
using System.Configuration;
string connStr = ConfigurationManager.ConnectionStrings["abcConnectionString"].ConnectionString;
SqlConnection Con = new SqlConnection(connStr);

Use Enterprise library to handle your data access code.

Related

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.

Database connection simplified - Is this right?

I'm trying to teach myself c#, and have found various examples on connecting to a MSSQL database. What I've done seems to be the simplest way to do it, but still seems overly complicated.
Is there a better way?
here's my code:
static void dbcon()
{
List<int> familyID = new List<int>();
String connString = "Server=[myServer]\\[myInstance];Database=[dbName];User Id=[userID};Password=[password];";
using (var sqlconn = new SqlConnection(connString))
{
using (var cmd = sqlconn.CreateCommand())
{
try
{
sqlconn.Open();
cmd.CommandText = "SELECT id FROM family";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
familyID.Add(Convert.ToInt32(reader["id"].ToString()));
}
}
foreach (int tempy in familyID)
{
Console.WriteLine("id: " + tempy);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
This is fine for an app that only runs one sql statement, but you wouldn't want to use all that code every time you wanted new data.
What you want to do is separate the code that creates the connection, from the code that gets and runs the sql, from the code that deals with the results.
This way, the connection code (and possibly the data display code) can be written once and called each time you want to execute different sql, and you only have to concentrate on how to write the code that gets the data you want.
hth
Details: First of all welcome to Stackoverflow. Just a few tips below
Having your connection string hard coded like that is bad practice. You should ALWAYS have it in your App.config (or Web.config if it is a web application). The reason is because if you have it hard coded and your boss ask you to change the Applications Database connection string you will need to recompile the entire application. If you have it in a App.config file you just need to change it (open it up with notepad) and save it.
Example on how to add it to the app.config
<configuration>
<connectionStrings>
<add name="myConnectionString"
connectionString="Data Source=localhost;Initial Catalog=MySQLServerDB;
Integrated Security=true" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
Then to access it in your code (You will need to add a reference to System.Configuration as well as add using System.Configuration;)
string connString = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
In regards to your other code I would change your exception catching to include the Sql Exception first and then fall back to any other exceptions.
catch (SqlException ex)
{
// Handle the Sql Exception code
}
catch (Exception ex)
{
// Handle the Normal Exception code
}
The example contained in the docs for SqlConnectionStringBuilder is quite easy to follow and understand as an alternative way.
System.Data.SqlClient.SqlConnectionStringBuilder builder =
new System.Data.SqlClient.SqlConnectionStringBuilder();
builder["Data Source"] = "(local)";
builder["integrated Security"] = true;
builder["Initial Catalog"] = "AdventureWorks;NewValue=Bad";
Console.WriteLine(builder.ConnectionString);
Edit:
Actually, the example I copied above shows you how the SqlConnectionStringBuilder class handles an "...invalid value in a safe manner". Whoops. At least it gives you an idea of how it works.
For more info on the various methods of obtaining, storing and constructing your connection string within ADO.NET, look at the MSDN documentation on Connection Strings

How to display data in gridview from MS Access?

I want to display information of user stored in a MS Access database. The user enters his userid and on clicking a button following function is called. But no data is being displayed. What am I doing wrong ?
System.Data.OleDb.OleDbConnection con;
System.Data.OleDb.OleDbDataAdapter da;
protected void Button1_Click(object sender, EventArgs e)
{
con = new System.Data.OleDb.OleDbConnection();
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=C:\\Users\\sam\\Desktop\\mydb.mdb";
con.Open();
string sql = "SELECT * From Leave where userid="+Textbox1.Text;
da = new System.Data.OleDb.OleDbDataAdapter(sql, con);
DataTable t = new DataTable();
da.Fill(t);
GridView1.DataSource = t;
con.Close();
}
You need to call GridView1.DataBind()
GridView1.DataSource = t;
GridView1.DataBind();
Just a side-note, it is good practice to wrap your connection with using
using(con = new System.Data.OleDb.OleDbConnection())
{
con = new System.Data.OleDb.OleDbConnection();
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=C:\\Users\\sam\\Desktop\\mydb.mdb";
con.Open();
...
...
}
This ensures your connection is properly disposed after use
You should use bind function:
protected void Button1_Click(object sender, EventArgs e)
{
con = new System.Data.OleDb.OleDbConnection();
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=C:\\Users\\sam\\Desktop\\mydb.mdb";
con.Open();
string sql = "SELECT * From Leave where userid="+Textbox1.Text;
da = new System.Data.OleDb.OleDbDataAdapter(sql, con);
DataTable t = new DataTable();
da.Fill(t);
GridView1.DataSource = t;
GridView1.DataBind();
con.Close();
}
First off, please, please please don't concatenate your WHERE parameters in your SQL. Use Parameters. Second, Add a "using System.Data.OleDb" statement at the top of your module, so that you are not having to type things like:
System.Data.OleDb.OleDbDataAdapter
Over and over again.
Try the following code. Personally, when I have to work with data tables and such, I prefer to avoid all the DataAdapter nonsense, and keep it as simple as possible.
Note in the code below:
the "using" blocks. These place the variables created within them inside their own scope, and take care of disposal and such for you.
I used an OleDb Parameter instead of concatenating criteria. This is a much safer way to do things, and creates much cleaner and more readable code as well, especially in cases where you have several criteria in your WHERE clause.
I assume your UserID input is a string, since you are grabbing the value from a Textbox. If it is in fact an int value (such as an auto-incrementing id in MS Access) you will need to use an int data type instead. You may have to mess with it a little. When you are still figuring this stuff out, it can be a bit painful. However, using parameters increases security and maintainability.
Once you have obtained a data table as the return from the MyUsers method, you should be able to simply set the data source of your Gridview. If you have difficulties still, do as Steve suggests and check the Autogenerate columns property in the designer, or set it in code.
Not that I have moved the connection string to the project Properties/Settings. You should find this in the solution designer. Place your connection string there, in one spot, and you can obtain it from anywhere in your code. If you later change the connection string (such as moving your Db to another computer, server share, etc) you need only change it in one place.
SAMPLE CODE:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb; // put this here, and stop writing long namespaces inline
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Where possible, move code out of specific event handlers
// into methods which can be re-used from other client code.
// Here, I pulled the actual data access out into separate methods,
// and simply call it from the event handler:
this.LoadGridView(textBox1.Text);
}
private void LoadGridView(string UserID)
{
// Now we can load the gridview from other places in our
// code if needed:
this.dataGridView1.DataSource = this.MyUsers(UserID);
}
private DataTable MyUsers(string UserID)
{
var dt = new DataTable();
// Use a SQL Paramenter instead of concatenating criteria:
string SQL = "SELECT * FROM Leave WHERE userid = #UserID";
// The "using" statement limits the scope of the connection and command variables, and handles disposal
// of resources. Also note, the connection string is obtained from the project properties file:
using(OleDbConnection cn = new OleDbConnection(Properties.Settings.Default.MyConnectionString))
{
using (var cmd = new OleDbCommand(SQL, cn))
{
// For simpler things, you can use the "AddWithValue" method to initialize a new parameter,
// add it to the Parameters collection of the OleDBCommand object, and set the value:
cmd.Parameters.AddWithValue("#UserID", UserID);
// Get in, get out, get done:
cn.Open();
dt.Load(cmd.ExecuteReader());
cn.Close();
}
}
return dt;
}
}
}
Hope that helps. It's not how everyone might do it, but I have found it provides maximum flexibility, when you must work with MS Access.

can't find the logical error in c# asp.net below

I wrote this code to get data from mysql database using odbc connection. Its giving no error but no output as well. Am not able to find what the matter is.
public partial class Members : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DataTable table = new DataTable();
string conString = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
try
{
using (OdbcConnection con = new OdbcConnection(conString))
{
con.Open();
// We are now connected. Now we can use OdbcCommand objects
// to actually accomplish things.
using (OdbcCommand com = new OdbcCommand("SELECT * FROM abc", con))
{
using (OdbcDataAdapter ad = new OdbcDataAdapter(com))
{
ad.Fill(table);
}
}
con.Close();
}
}
catch (Exception ei)
{
Label1.Text = ei.Message;
}
GridView1.DataSource=table;
GridView1.DataBind();
}
}
In web.config do you have a connectionString? Please check that.
If not you can add datasource from visual studio designer and it will ask to add connection string in one of the steps .At the end you can remove datasource from designer but still have connectionstring in web.config file .And in your code behind can you try this
string SQL_CONNECTION_STRING = System.Configuration.ConfigurationManager.ConnectionStrings["SqlConnectionTest"].ConnectionString;
where "SqlConnectionTest" is the name of connection string in web.config.
The problem was that I converted a vb project just by replacing the c# file with the vb ones to make it a c# project, and this created this whole mess.The code work perfectly fine when done on a new projects.

Session variables being broken by an unrelated method

I have a problem that is completely boggling me as it makes absolutely no sense. Ok, as I understand and have used in the past, to pass variables from one page to another via session, you simply say
Session["variableName"] = value;
Then to use it in the receiving page, it something like:
string container = Session["variableName"].ToString();
Right? Dandy. In my code (at least this particular application, anyway), I'm find that I can't set any session variables if I have a method in my page_load of the code-behind:
protected void Page_Load(object sender, EventArgs e)
{
Session.Add("values", "It Worked");
LoadAvailableItems();
}
This will cause the application to not pass the variable to the next page. However, if I remove the LoadAvailableItems() method, it will work just fine. So now you'll ask me "ok, so show us whats inside of that method". It is just a test connection to run dummy data for a control:
//test connection DELETE ME
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
+ Server.MapPath("App_Code/temp/cokeDb.mdb") + ";Persist Security Info=False;";
OleDbConnection conn = new OleDbConnection(connString);
string sql = "select docNum, docName from lut_docs order by docNum";
OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
DataSet ds = new DataSet();
conn.Open();
da.Fill(ds);
conn.Close();
cblstAvailableItems.DataSource = ds;
cblstAvailableItems.DataTextField = "docName";
cblstAvailableItems.DataValueField = "docNum";
cblstAvailableItems.DataBind();
//end test connection
From what I was able to narrow it down to through commenting out blocks and running the application, I think it is related to this block:
conn.Open();
da.Fill(ds);
conn.Close();
Now WHY this is causing a problem, I do not understand in the slightest. If someone could explain this to me, I may refrain from putting my head through a wall.

Categories