C# passing information - c#

Sorry in advance im going to try and explain this as best as possible....
I have 2 asp.net pages one named membermaster and the second named memberdetails. I created a class library which contains 2 functions
My first function returns a list depending on the search result...
I added a linkbutton to the gridviews first column which when clicked it passes through querystring the membershipgen. What i wanted to do is for my second function i created this
public DataTable GetMembers(int MEMBERSHIPGEN)
{
DataTable table = null;
SqlConnection con = null;
SqlCommand cmd = null;
SqlDataAdapter ad = null;
SqlParameter prm = null;
try
{
table = new DataTable();
using (con = new SqlConnection(connectionString))
{
using (cmd = new SqlCommand("usp_getmemberdetail", con))
{
using (ad = new SqlDataAdapter(cmd))
{
prm = new SqlParameter("#MEMBERSHIPGEN", SqlDbType.Int);
prm.Value = MEMBERSHIPGEN;
cmd.Parameters.Add(prm);
ad.Fill(table);
}
}
}
}
catch (Exception ex)
{
//write your exception code here
}
return table;
}
In the attempt to try and send the membershipgen to this and it return the results. But once i compile the DLL and add it to my project I am not sure how i would reference this function to populate individual textboxes and labels with the information.
What I am trying to do is when a user clicks the viewdetails button on the gridview I can then use that membershipgen that I passed through querystring to populate the page through a stored procedure but the smarts would be stored in a DLL.

You probably want your method to return a value. Currently the return type is void, so the values it populates internally just go away when the call stack leaves the method. It sounds like you want something like this:
public DataTable GetMembers(int MEMBERSHIPGEN)
Then, in your method, after you've populated the DataTable and exited the using blocks, you'd do something like this:
return table;
This would return the DataTable to whatever called the method. So your page would have something like this:
DataTable table = GetMembers(membershipgen);
So the page would be responsible for:
Get the membershipgen value from the input (query string)
Call the method and get the result of the method
Display the result from the method (bind to a grid? or whatever you're doing to display the data)
And the method is responsible for:
Interact with the database
This is a good first step toward the overall goal of "separation of concerns" which is a very good thing to do. You can continue down this path by always asking yourself what each method, class, etc. should be responsible for. For example, your GetMembers method should also be responsible for ensuring that the value passed to it is valid, or that the value returned from it is not null.

You need to change GetMembers to return data instead of void. If you want to use DataTables, you can just modify your code to this:
public DataTable GetMembers(int MEMBERSHIPGEN)
{
DataTable table = new DataTable();
SqlConnection con = new SqlConnection(connectionString);
using (SqlCommand cmd = new SqlCommand("usp_getmemberdetail", con))
{
using (SqlDataAdapter ad = new SqlDataAdapter(cmd))
{
SqlParameter prm = new SqlParameter("#MEMBERSHIPGEN", SqlDbType.Int);
prm.Value = MEMBERSHIPGEN;
cmd.Parameters.Add(prm);
ad.Fill(table);
return table;
}
Then in your Page_Load it might be something like this (more robust than this hopefully):
{
DataTable table = yourDll.GetMembers(Convert.ToInt32(Request.QueryString["membership"]));
label1.Text = Convert.ToString(table.rows[0]["Name"]);
}

One way to go might be to construct the button so that it navigates to a url along the lines of:
http://localhost/DetailPage.aspx?membershipgen=4
Then in the load of the DetailPage.aspx:
Page_Load(Object sender, EventArgs e)
{
if (!this.IsPostback)
{
int membershipgen;
if (int.TryParse(Request.QueryString["membershipgen"], out membershipgen)
{
//Get the data (replace DataAccess with the name of your data access class).
//Also, you probably want to change GetMembers so it returns the data.
DataTable table = DataAccess.GetMembers(membershipgen);
//TODO: Display the results
}
}
else
{
//Display an error
}
}

Related

Upserting a DataTable via a proc call C#

I have the following lines of code that call a proc and return the results of the proc call and place them into a DataTable
DataTable dt = new DataTable();
SqlDataAdapter data = new SqlDataAdapter();
_repo.ExecuteSprocPopulateDataTable(command, null, dt);
When I debug my code, my datatable is populated with the results as expected but I'm stuck on passing the data back up in to my database via another proc.
I've looked and seen some stuff about SqlDataAdapters and tried the following line:
data.Update(dt.DataSet, _command);
But when I do, it tells me that Value can not be null which relates to my dataset.
Can someone advise the best way for me to upsert my data via a proc call?
Not quite sure what that _command there is, but with SqlDataAdapters, updates typically go like this:
try
{
using (SqlCommandBuilder cb = new SqlCommandBuilder(data))
{
data.InsertCommand = cb.GetInsertCommand();
data.UpdateCommand = cb.GetUpdateCommand();
data.DeleteCommand = cb.GetDeleteCommand();
data.Update(dt);
}
}
catch (Exception ex)
{
// handle errors
}

how to prevent data overloading at different sessions using asp.net

I wrote some code for search page as follows
I declared variables in above page load as follows
static String strsql = "";
in page load
if(!isPostback)
{
if(session["username"] != null)
{
loadprofiles(); // calling loadprofiles method
bindlist();//loading gridview data
}
}
now loadprofiles method wrote as follows
protected void loadprofiles()
{
strsql = "select * from admintable where userid = '"+session["username"].Tostring()+"'";
}
now bindlist method is as follows
private void bindlist()
{
SqlCommand comm1 = new SqlCommand(strsql, connection);
//and some code for binding data to gridview
}
the problem is while two different users are login into this page from two different computers the user getting the data from second login persions
please help me to solve this problem...
thanks in advance
I was having Session issue for multiple tabs in a single browser.
In Default.aspx/Index.aspx write below code to generate a Unique session Id's.
if (Page.IsPostBack == false) //If page loads for the first time
{
ViewState["_PageID"] = Guid.NewGuid();
}
To store any variable in session Use the following lines:
Session[ViewState["_PageID"].ToString() + "username"] = "testuserName";
To access anything stored based on the Session Id:
string userNameInSession = Session[ViewState["_PageID"].ToString() + "username"] as string;
You cannot declare strsql as static since it will store value for all users - user1 will have access to the user2 strsql value. You have to remember that static is a member of a type, not an instance - it will be accessible for all users until AppDomain is unloaded.
In my opinion you shouldn't store SQL query in a variable(it seems unnecessary since session is accessible everywhere in your code).
I'd change your code to the
private void bindlist()
{
SqlCommand comm1 = new SqlCommand("select * from admintable where userid = '"+session["username"].Tostring()+"'", connection);
//and some code for binding data to gridview
}
EDIT:
Since you want to reuse query, you can return it from loadprofiles() method like follows:
protected string loadprofiles()
{
strsql = "select * from admintable where userid = '"+session["username"].Tostring()+"'";
// Do your logic there...
return strsql;
}
and use it:
if(!isPostback)
{
if(session["username"] != null)
{
var strsql = loadprofiles(); // calling loadprofiles method
bindlist(strsql);//loading gridview data
}
}
I believe you get the point.

Parametrized login to Database don't work

This is the first time I work with Object Oriented C# to Database so I am trying to make an login for my CRM-system with parameterized SQL-Query. The query check if the both the textboxes 'Username' and 'Password' match any records in the database and if it do, it fills an DataTable just for test purpose to see if anythings happens but nothings happens, the Da is empty all the time.
Here the code that should send text from textboxes to the parameterized query and then to the "Query Execution Method"
private void bLoggaIn_Click(object sender, EventArgs e)
{
string sql = "SELECT * FROM Anvandare WHERE anvandarnamn = #anvandarnamn AND losenord = #losenord";
SqlCommand sqlCmd = new SqlCommand(sql);
sqlCmd.Parameters.AddWithValue("#anvandarnamn", tbAnvandarnamn.Text.Trim().ToString());
sqlCmd.Parameters.AddWithValue("#losenord", tbLosenord.Text.Trim().ToString());
clsDB.ReadFromDatabase(sqlCmd);
}
This is the method that should execute the query against the database and then return 0 if there is no match or 1 if there is a match but for now, it just fills a DataTable with the matched record, just for test purpose but it don't work, the DataTable is always empty which means it didn't find any match.
public static void ReadFromDatabase(SqlCommand sqlCmd)
{
try
{
if (!(anslutning.State == ConnectionState.Open))
anslutning.Open();
sqlCmd.Connection = anslutning;
SqlDataAdapter sqlDa = new SqlDataAdapter();
sqlDa.SelectCommand = sqlCmd;
DataTable dt = new DataTable();
sqlDa.Fill(dt);
anslutning.Close();
}
catch (SqlException undantag)
{
string felmeddelande = undantag.Message;
}
}
So why does it not work? I don't understand it should work or have I missed something?
Do you realy want to use the textbox tbLosenord twice?
sqlCmd.Parameters.AddWithValue("#anvandarnamn", tbLosenord.Text.Trim().ToString());
sqlCmd.Parameters.AddWithValue("#losenord", tbLosenord.Text.Trim().ToString());
For such problems I set a break point (click on the left side of your code editor window in Visual Studio) and use the debugger. The MSDN has many tutorials on the debugger and you can find videos on YouTube to explain it in a more beginner friendly way.

Retrieve/insert data using SQLiteDataAdapter

I'm currently creating a small application using Windows Forms and SQLite. After reading some tutorials I implemented this method for data retrieval:
public DataTable GetDataTable(ref SQLiteDataAdapter adapter, string sql)
{
DataTable dt = new DataTable();
// Connect to database.
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
// Create database adapter using specified query
using (adapter = new SQLiteDataAdapter(sql, connection))
// Create command builder to generate SQL update, insert and delete commands
using (SQLiteCommandBuilder command = new SQLiteCommandBuilder(adapter))
{
// Populate datatable to return, using the database adapter
adapter.Fill(dt);
}
return dt;
}
(As well as another GetDataTable which doesn't take an SQLiteDataAdapter as parameter)
I have three classes, let's call them UI, Link and Database. The UI does nothing but displaying the data and raising events upon user interaction. The Link creates the Database and a SQLiteDataAdapter, retrieves a data table through the method mentioned above, and binds it to a data grid view on the UI. The user cannot alter the table through the data grid view, but should do so through some text boxes. (does this make binding the table to the dgv obosolete?)
What's the best way to get the user input from the text boxes to the database, using the adapter? Or should I use DataReader and some Insert method instead of an adapter?
As of know, the UI exposes its controls through Get-methods. Is there a better solution?
private void Initialize()
{
// Subscribe to userInterface events
userInterface.DataGridViewSelectionChanged += new EventHandler(userInterface_DataGridViewSelectionChanged);
userInterface.NewClicked += new EventHandler(userInterface_NewClicked);
userInterface.SaveClicked += new EventHandler(userInterface_SaveClicked);
// Get dataGridView from userInterface and bind to database
bindingSource = new BindingSource();
bindingSource.DataSource = database.GetDataTable(ref adapter, "SELECT * FROM SomeTable");
userInterface.GetDataGridView().DataSource = bindingSource;
}
void userInterface_DataGridViewSelectionChanged(object sender, EventArgs e)
{
if (userInterface.GetDataGridView().SelectedRows.Count != 0)
{
DataGridViewRow row = userInterface.GetDataGridView().SelectedRows[0];
userInterface.GetIDTextBox().Text = row.Cells["PrimaryKey].Value.ToString();
userInterface.GetOtherIDTextBox().Text = row.Cells["ForeignKey"].Value.ToString();
DataTable dt = database.GetDataTable("SELECT * from SomeTable WHERE ForeignKey=" + row.Cells["ForeignKey"].Value);
userInterface.GetLastNameTextBox().Text = dt.Rows[0]["LastName"].ToString();
userInterface.GetFirstNameTextBox().Text = dt.Rows[0]["FirstName"].ToString();
userInterface.GetCompanyTextBox().Text = dt.Rows[0]["Company"].ToString();
}
}
void userInterface_NewClicked(object sender, EventArgs e)
{
// Get all text boxes and clear them
// Let the UI take care of this by itself?
}
void userInterface_SaveClicked(object sender, EventArgs e)
{
// Get text/data from all text boxes and insert (or update if editing table) into database
// adapter.Update(...)?
}
Cheers!
INSERT, UPDATE and DELETE operations are the working of a DbCommand. You need a different method that takes the sql string and a collection of SQLiteParameter that you use for the INSERT.
I will try to write some pseudocode for the INSERT operation
public class MyHelperClass
{
public static int InsertCommand(string sql, SQLiteParameter[] parameters)
{
int result = 0;
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
using (SQLiteCommand cmd = new SQLiteCommand(sql, connection))
{
cmd.Parameters.AddRange(parameters);
result = cmd.ExecuteNonQuery();
}
return result;
}
}
Now you have to build the parameter array to pass to the help method and this should be done from your UI code
string sqlCommand = "INSERT INTO table1 (FirstName, LastName) VALUES (#fName, #lName)";
SQLiteParameter[] p = new SQLiteParameter[2];
p[0] = new SQLiteParameter("#fName", TextBox1.Text);
p[1] = new SQLiteParameter("#lName", TextBox2.Text);
int rowAdded = MyHelperClass,InsertCommand(sql, p);
The operation for the UPDATE and DELETE command are similar. Also I suggest you to add a version of your GetDataTable that accepts a parameter array instead of building sql commands with string concatenation. As repetead innumerable times here string concatenation leads to errors and, worst of all, to weak code easily exposed to sql injection.

How to show data using datagrid with C# + SQL Server

I want to ask more to show data from SQL Server to WinForm using a datagrid.
I've been creating a datagrid and the stored procedure to show data is
ALTER PROC [dbo].[SP_GetData]
AS
SELECT nama , nim
FROM tabledata
and I've created the function to access the database and the stored procedure in C#
string Sp_Name = "dbo.SP_GetData";
SqlConnection SqlCon = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBMahasiswa;Data Source=.");
SqlCon.Open();
SqlCommand SqlCom = new SqlCommand(Sp_Name , SqlCon);
SqlCom.CommandType = CommandType.StoredProcedure;
List<mahasiswaData> listMahasiswa = new List<mahasiswaData>();
using (SqlDataReader sqlDataReader = SqlCom.ExecuteReader())
{
if (sqlDataReader.HasRows)
{
while (sqlDataReader.Read())
{
mahasiswaData DataMhs = new mahasiswaData();
DataMhs.Nama = sqlDataReader["Name"].ToString();
DataMhs.Umur = Convert.ToInt32(sqlDataReader["Age"]);
listMahasiswa.Add(DataMhs);
}
}
}
SqlCon.Close();
return listMahasiswa;
and finally, in the show button I add this code
dgvmahasiswa.DataSource = new MahasiswaDB().LoadMahasiswa();
Could somebody tell me where the fault is or the alternatives one?
Thank You So Much! :D
Some things to think about:
At the moment, if your code runs into exceptions, you'll leave a
SqlConnection hanging around; you've used the using pattern for your
SqlDataReader; you should extend it to all of your disposable
objects.
You are swallowing exceptions; if your query fails, the connection
cannot be made, or something else happens, you'll never really know - your function will just return null.
Is it possible for name or age to be null? Age to be non-numeric?
There's no test for any unexpected values, which you'll also never
know about.
If you don't have any records, you'll return an empty list. Is this
desired? Or would you prefer to know there were no records?
You might prefer to look at something like this:
public List<mahasiswaData> GetData(){
List<mahasiswaData> gridData = new List<mahasiswaData>();
try{
using(SqlConnection conn = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBMahasiswa;Data Source=."))
{
using(SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.Text = "dbo.SP_GetData";
using(SqlDataReader reader = command.ExecuteReader())
{
if(reader.HasRows){
while(reader.Read())
{
object rawName = reader.GetValue(reader.GetOrdinal("Name"));
object rawAge = reader.GetValue(reader.GetOrdinal("Age"));
if(rawName == DBNull.Value || rawAge == DBNull.Value)
{
//Use logging to indicate name or age is null and continue onto the next record
continue;
}
//Use the object intializer syntax to create a mahasiswaData object inline for simplicity
gridData.Add(new mahasiswaData()
{
Nama = Convert.ToString(rawName),
Umur = Convert.ToInt32(rawAge)
});
}
}
else{
//Use logging or similar to record that there are no rows. You may also want to raise an exception if this is important.
}
}
}
}
}
catch(Exception e)
{
//Use your favourite logging implementation here to record the error. Many projects use log4Net
throw; //Throw the error - display and explain to the end user or caller that something has gone wrong!
}
return gridData;
}
Note that if you are sure that age or name will never be null then you can simplify the middle section:
while (reader.Read())
{
//Use the object intializer syntax to create a mahasiswaData object inline for simplicity
gridData.Add(new mahasiswaData()
{
Nama = reader.GetString(reader.GetOrdinal("Name")),
Umur = reader.GetInt32(reader.GetOrdinal("Age"))
});
}

Categories

Resources