Retrieving DropDownList 'value' (C#/ASP.NET) - c#

On my page, whenever a DetailsView is updated, I must audit the changes into a database. On most pages this works perfect, as there were just textboxes - however on a page I am working on right now, with dropdownlists, my code isn't working.
Basically, what the code does is captures the Updating event of the SqlDataSource, creates a datareader to look at the contents of the row before it's updated, compares the contents to the parameters in the Update query of the SqlDataSource, and if one has changed to log this in a field in the Audit table. An extract of my code is below:
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
try {
if (reader[i].ToString() != e.Command.Parameters[i].Value.ToString())
{
fields[i] = reader.GetName(i) + ": " + reader[i].ToString() + " => " + e.Command.Parameters[i].Value.ToString();
}
}
catch {
if (reader[i].ToString() != "")
{
fields[i] = reader.GetName(i) + ": " + reader[i].ToString() + " => ";
}
}
}
}
When the control is on a dropdownlist, it seems to never go 'into' the IF even though the fields are different. Do I need to do something special to compare the values of dropdownlists? Note I believe the value is stored as an int in my table.
Thanks

Totally my fault. There was an extra parameter on the command which I had to exclude somehow.

Related

Check for key duplicates in Gridview Frontend ASP.NET C#

A person can have many bills.
Each bill can have many (Item, Quantity) entries.
My primary key is (Bill_No,Item_Code) .
For each Bill_no, I can enter a particular Item_Code only once.
I enter the (Item,Quantity) details via a Grid View as shown.
Can I validate this at the front end on Create Indent click so that an Item_no entered once in the gridView cannot be entered again before submit is clicked?
I have done the back end primary key validation in the Data Access Layer. It just ignores the duplicate Item_No and continues with an alert.
I want to check for duplicate Item_code entries row-wise via front end so no data is lost on create.
//to check repeated item in the gridview
int rowIndex = 0;
if (ViewState["CurrentTable"] != null)
{
DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
if (dtCurrentTable.Rows.Count > 1)
{
for (int i = 1; i <= dtCurrentTable.Rows.Count-1; i++)
{
if (dtCurrentTable.Rows.Count > 1)
{
TextBox prevItem = (TextBox)Grid_ItemList.Rows[rowIndex].Cells[1].FindControl("itemCode");
if (prevItem.Text == itemcode && currentRow.RowIndex != rowIndex)
{
ClientScript.RegisterStartupScript(Page.GetType(), "validation1", "<script language='javascript'>alert('Item Alredy Added, Please change the Qty if needed.')</script>");
txt.Text = "";
qtyl.Enabled = false;
return;
}
}
rowIndex++;
}
}
SetRowData();
}
put this code inside your dropdownlist onselected index change function, just before you populate the itemcode.
Even if you'd check it against the data in your grid it would be possible that paging is enabled. Then the grid only stores the data of the current page.
Apart from that, even without paging you'll have the problem that another user could add a record at the same time with the same Bill_no+Item_Code.
So there is no other/better way than to handle the constraint exception of the database. Therefore you need to add an unique index on the combination of Bill_no+Item_Code.
Assuming SQL-Server as rdbms, you can use the SqlException's Number property:
string error = "";
try
{
CreateIndent();
} catch (SqlException ex)
{
switch (ex.Number)
{
case 2627: // Unique Index/ Primary key Violation/ Constraint Violation
case 2601: // Unique Index/Constraint Violation
error = "Bill_no and Item_Code are not unique";
break;
default:
error = "Unknown SQL-Exception";
break;
}
}
// show error
Update
Suppose I enter (Apple,10) , (Apple,20) and (Apple,40) as three items
of my gridview, my only option is to have (Apple,10) enter the
database and the other entries error out?
string
unique=((TextBox)Grid_ItemList.Rows[rowIndex].Cells1.FindControl("itemCode")).‌​ToString();
This is how I get my data in each row. Now how do I check for
uniqueness?
If you insist on checking the GridView row by row which won't work with paging or if another user uses this page simultaneously, this should work:
var allItems = Grid_ItemList.Rows.Cast<GridViewRow>()
.GroupBy(r => new {
ItemValue = ((DropDownList)r.FindControl("DdlItemName")).SelectedValue,
ItemCode = ((TextBox) r.FindControl("itemCode")).Text.Trim()
});
var duplicates = allItems.Where(g => g.Count() > 1);
// show somewhere on the page, for example on an error-panel or label
LblError.Text = "Duplicates detected: " +
string.Join(",", duplicates.Select(d => d.ToString()));
Of course you could also use a loop to check if all combinations are unqiue.

Update query fails to update rows value in DataGridView

I have a form, containing a button to add DataGridView rows and another button to delete the selected row. I'm using this code to save :
private void SaveReq2()
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
this.mysql.sa.InsertCommand.CommandText = "INSERT INTO molaak_det(MAXID,MALKID,AKARTYPE,AKARADDRESS) VALUES ('" + this.dataGridView1.Rows[i].Cells[2].Value + "','" + txtID.Text + "','" + this.dataGridView1.Rows[i].Cells[0].Value + "','" + this.dataGridView1.Rows[i].Cells[1].Value + "')";
mysql.sa.InsertCommand.ExecuteNonQuery();
}
}
The save process works good but, when I want to update using the query, I'm updating only the current rows. If I insert a new row and then I have to update, the code saves this new row in the database. Here my UPDATE query :
private void UpdateReq2()
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
mysql.sa.UpdateCommand.CommandText = string.Format(" UPDATE molaak_det SET MALKID='{1}',AKARTYPE='{2}',AKARADDRESS='{3}' where MAXID='{0}'", this.dataGridView1.Rows[i].Cells[2].Value, txtID.Text, this.dataGridView1.Rows[i].Cells[0].Value, this.dataGridView1.Rows[i].Cells[1].Value);
mysql.sa.UpdateCommand.ExecuteNonQuery();
}
}
Please, I need help to write well the UPDATE query. Thanks.
I suspect that your update command is trying to update data types incorrectly... first things first it is pretty unsecure, you should at least parameterise the sql...
Have a read of this tutorial / example on how to do it, it is pretty easy, must more secure and much more type safe than what you are doing. http://www.dotnetperls.com/sqlparameter
P.S. It helps if you could put details of any error, not just say it doesn't work... e.g is the power plug in on the DB server, is that why it doesn't work? :D
I don't understand quite well your process.
You should execute, while adding a new row to the DataGridView, the INSERT query, because you cannot do this with an UPDATE query.
Then, you have to understand in your control what rows have been added and proceed with the INSERT query.
Once this process completed, you can update the existing rows with an UPDATE query.
I agree with #PaulZahra, improve your queries using SqlParameter objects.

Getting values from templatefields gridview - C#

I am using a gridview to display a table queried from a database...
In this gridview I also added a buttonfield, and 3 template fields...
When i press the buttonfield the data from the database is acquired, but the
manual data inserted from the template fields are not.. It seems that null values are acquired.
From the xml file i am firing the following event:
OnRowCommand="GridView1_SelectedIndexChanged1"
and have the following method to catch that event:
protected void GridView1_SelectedIndexChanged1(object sender, GridViewCommandEventArgs e)
{
int x = Convert.ToInt32(e.CommandArgument);
GridView1.SelectRow(x);
GridViewRow row = GridView1.Rows[x];
Response.Write(row.Cells[0].Text + "\t");
Response.Write(row.Cells[1].Text + "\t");
Response.Write(row.Cells[2].Text + "\t");
Response.Write(row.Cells[3].Text + "\t");
Response.Write(row.Cells[4].Text + "\t");
Response.Write(row.Cells[5].Text + "\t");
Response.Write(row.Cells[6].Text + "\t");
Response.Write(row.Cells[7].Text + "\t");
Response.Write(row.Cells[8].Text + "\t");
}
Any ideas on how i can get the values from that template field? do i need to catch another event rather than GridViewCommandEventArgs? If so what event should i throw from the xml part?
Thanks,
You can find the control u added on to the row and then use the text property to get the value of it.
Something similar to row.FindControl(<urIdgoeshere>)\\cast it to textBoxand then use .Text to get the value of it .
GridViewRow row = GridView1.Rows[x];
Response.Write((TextBox)row.FindControl('txtbox1')).Text;
I am fighting with the same, I used to use the Cells[] code with asp BoundField.
Now i had to switch to template fields as I need buttons etc in the footer.
I am pulling my hair out, I use the same code as suggested by Ashley, and I get System.NullReferenceException: Object reference not set to an instance of an object.
I am doing this within the row command event.
Been this way since 3 days :(
Edit:
Quick Solution to my issue: I've created the ID given Field on the footer, and I had not given and ID to my ItemTemplate, i.e the only thing I had in there was <%# Eval("Description")%>
There looks like to be NO WAY to select this data without giving it some kind of ID in code behind. I was stupid and had not noticed this simple fact later on.

c# search ms access db by ID

private void Filtriraj()
{
string filter = string.Empty;
if (txtID.Text.Length > 0)
{
filter = "ID LIKE '%" + txtID.Text + "%'";
}
if (txtName.Text.Length > 0)
{
filter = "Name LIKE '%" + txtName.Text + "%'";
}
}
I want to search thru ms access db tables in my c# app. The one above is connected to "Table1" that has some fields like ID, name, surname, address...ID type is set to autonumber, all others are to text. I'm able to search all fields except by ID, this way above wont work, i get exception when i try to search by ID (I type in txtbox some ID number that is in db, exmp: '1')
Search by txtName is working fine.
Autonumber is some form of number (long I think) so you can't use the LIKE keyword. You must search for an exact match (or greather than, less than etc.). You also can't surround a number with single quotes, so those will need to be removed.
I'd switch your code to something like this:
.
.
.
if (txtID.Text.Length > 0)
{
int id;
if (Int32.TryParse(txtID.Text, out id))
{
filter = "ID = " + id.ToString();
}
}
.
.
.
Also, your code looks like it may not work properly if you have multiple text boxes filled with data (because you are not using else if). Whatever text box you check last will end up being the filter that gets used because you're reassigning the filter variable each time. And if you're using the filter text directly from the text boxes, you're opening yourself up to possible SQL Injection. You should probably look into using parameterized queries.

C# : Forcing a clean run in a long running SQL reader loop?

I have a SQL data reader that reads 2 columns from a sql db table.
once it has done its bit it then starts again selecting another 2 columns.
I would pull the whole lot in one go but that presents a whole other set of challenges.
My problem is that the table contains a large amount of data (some 3 million rows or so) which makes working with the entire set a bit of a problem.
I'm trying to validate the field values so i'm pulling the ID column then one of the other cols and running each value in the column through a validation pipeline where the results are stored in another database.
My problem is that when the reader hits the end of handlin one column I need to force it to immediately clean up every little block of ram used as this process uses about 700MB and it has about 200 columns to go through.
Without a full Garbage Collect I will definately run out of ram.
Anyone got any ideas how I can do this?
I'm using lots of small reusable objects, my thought was that I could just call GC.Collect() on the end of each read cycle and that would flush everything out, unfortunately that isn't happening for some reason.
Ok i hope this fits but here's the method in question ...
void AnalyseTable(string ObjectName, string TableName)
{
Console.WriteLine("Initialising analysis process for SF object \"" + ObjectName + "\"");
Console.WriteLine(" The data being used is in table [" + TableName + "]");
// get some helpful stuff from the databases
SQLcols = Target.GetData("SELECT Column_Name, Is_Nullable, Data_Type, Character_Maximum_Length FROM information_schema.columns WHERE table_name = '" + TableName + "'");
SFcols = SchemaSource.GetData("SELECT * FROM [" + ObjectName + "Fields]");
PickLists = SchemaSource.GetData("SELECT * FROM [" + ObjectName + "PickLists]");
// get the table definition
DataTable resultBatch = new DataTable();
resultBatch.TableName = TableName;
int counter = 0;
foreach (DataRow Column in SQLcols.Rows)
{
if (Column["Column_Name"].ToString().ToLower() != "id")
resultBatch.Columns.Add(new DataColumn(Column["Column_Name"].ToString(), typeof(bool)));
else
resultBatch.Columns.Add(new DataColumn("ID", typeof(string)));
}
// create the validation results table
//SchemaSource.CreateTable(resultBatch, "ValidationResults_");
// cache the id's from the source table in the validation table
//CacheIDColumn(TableName);
// validate the source table
// iterate through each sql column
foreach (DataRow Column in SQLcols.Rows)
{
// we do this here to save making this call a lot more later
string colName = Column["Column_Name"].ToString().ToLower();
// id col is only used to identify records not in validation
if (colName != "id")
{
// prepare to process
counter = 0;
resultBatch.Rows.Clear();
resultBatch.Columns.Clear();
resultBatch.Columns.Add(new DataColumn("ID", typeof(string)));
resultBatch.Columns.Add(new DataColumn(colName, typeof(bool)));
// identify matching SF col
foreach (DataRow SFDefinition in SFcols.Rows)
{
// case insensitive compare on the col name to ensure we have a match ...
if (SFDefinition["Name"].ToString().ToLower() == colName)
{
// select the id column and the column data to validate (current column data)
using (SqlCommand com = new SqlCommand("SELECT ID, [" + colName + "] FROM [" + TableName + "]", new SqlConnection(ConfigurationManager.ConnectionStrings["AnalysisTarget"].ConnectionString)))
{
com.Connection.Open();
SqlDataReader reader = com.ExecuteReader();
Console.WriteLine(" Validating column \"" + colName + "\"");
// foreach row in the given object dataset
while (reader.Read())
{
// create a new validation result row
DataRow result = resultBatch.NewRow();
bool hasFailed = false;
// validate it
object vResult = ValidateFieldValue(SFDefinition, reader[Column["Column_Name"].ToString()]);
// if we have the relevant col definition lets decide how to validate this value ...
result[colName] = vResult;
if (vResult is bool)
{
// if it's deemed to have failed validation mark it as such
if (!(bool)vResult)
hasFailed = true;
}
// no point in adding rows we can't trace
if (reader["id"] != DBNull.Value && reader["id"] != null)
{
// add the failed row to the result set
if (hasFailed)
{
result["id"] = reader["id"];
resultBatch.Rows.Add(result);
}
}
// submit to db in batches of 200
if (resultBatch.Rows.Count > 199)
{
counter += resultBatch.Rows.Count;
Console.Write(" Result batch completed,");
SchemaSource.Update(resultBatch, "ValidationResults_");
Console.WriteLine(" committed " + counter.ToString() + " fails to the database so far.");
Console.SetCursorPosition(0, Console.CursorTop-1);
resultBatch.Rows.Clear();
}
}
// get rid of these likely very heavy objects
reader.Close();
reader.Dispose();
com.Connection.Close();
com.Dispose();
// ensure .Net does a full cleanup because we will need the resources.
GC.Collect();
if (resultBatch.Rows.Count > 0)
{
counter += resultBatch.Rows.Count;
Console.WriteLine(" All batches for column complete,");
SchemaSource.Update(resultBatch, "ValidationResults_");
Console.WriteLine(" committed " + counter.ToString() + " fails to the database.");
}
}
}
}
}
Console.WriteLine(" Completed processing column \"" + colName + "\"");
Console.WriteLine("");
}
Console.WriteLine("Object processing complete.");
}
Could you post some code? .NET's data reader is supposed to be a 'fire-hose' that is stingy on RAM unless, as Freddy suggests, your column-data values are large. How long does this validation+DB write take?
In general, if a GC is needed and can be done, it will be done. I may sound like a broken record but if you have to GC.Collect() something else is wrong.
Open the reader with Sequential access, it might give you the behavior you need. Also, assuming that's a blob, you might also be better off by reading it in chunks.
Provides a way for the DataReader to handle rows that contain columns with large binary values. Rather than loading the entire row, SequentialAccess enables the DataReader to load data as a stream. You can then use the GetBytes or GetChars method to specify a byte location to start the read operation, and a limited buffer size for the data being returned.
When you specify SequentialAccess, you are required to read from the columns in the order they are returned, although you are not required to read each column. Once you have read past a location in the returned stream of data, data at or before that location can no longer be read from the DataReader. When using the OleDbDataReader, you can reread the current column value until reading past it. When using the SqlDataReader, you can read a column value can only once.

Categories

Resources