Get updated row in ASPxGridView.RowUpdating event with composite KeyFieldName - c#

I'm trying to create a custom edit script for my ASPxGridView. I have a second grid in which I used the code below to obtain the row that has been updated. This, however, doesn't work because my grid has a composite KeyFieldName (because the table it's based on has a primary key made up of two columns). This results in the FindVisibleIndexByKeyValue method always returning -1.
Any ideas on how I could obtain the row some other way?
object key = e.Keys[grid.KeyFieldName];
int row = grid.FindVisibleIndexByKeyValue(key);
Edit: The problem actually is that e.Keys[grid.KeyFieldName] returns null.

This can be accomplished by saving the keys into an array of objects one by one and passing that array to FindVisibleIndexByKeyValue().
object[] key = new object[2];
key[0]= e.Keys["firstKey"];
key[1] = e.Keys["secondKey"];
int row = grid.FindVisibleIndexByKeyValue(key);

Related

How do I populate a DataRow and assign it to one of two tables based on a condition?

I have data being processed by an app which needs to sort the data based on whether or not a bit is flipped. The tables are identical. The code as it stands looks something like this:
DataTable dt2 = dt1.Clone();
DataRow r = dt1.NewRow();
FillUp(ref r);
if(bitISetEarlier)
dt2.ImportRow(r);
else
dt1.ImportRow(r);
Now, a clear problem I was having is that if the row wasn't already attached to a table, ImportRow() fails silently and I end up with an empty table. When I changed this to:
if(bitISetEarlier)
dt2.Rows.Add(r);
else
dt1.Rows.Add(r);
I started getting an exception saying that a function was trying to add a row that existed for another table. So when I tried this:
if(bitISetEarlier)
if(r.RowState == DataRowState.Detached)
dt2.Rows.Add(r)
else dt2.ImportRow(r);
else
if(r.RowState == DataRowState.Detached)
dt1.Rows.Add(r)
else dt1.ImportRow(r);
the exception stopped, but any attempt to assign to dt2 still states that the row belongs to another table, but if I comment out the dt2 if statement and just attempt ImportRow(), the dt2.Rows.Count remains at 0 and no records assigned.
I need to populate the DataRow before knowing which table it belongs in, but I have no idea what columns the row will have before it hits this function. The condition that indicates which table it should go to is not stored with the data in the DataTable.
Is the problem that even though they have identical columns, NewRow() is adding an attribute to the row that makes it incompatible with the sister table? Is there a way I can get the same functionality as NewRow() (copy schema without knowing what any of the columns are ahead of time) but that I can dynamically assign? I'm aware I could probably manually construct a row that is compatible with either by wrapping it in a for loop and building out the columns every time i need the new row using the DataTable.Columns property, but I'd like to avoid doing that if possible.
I found my solution. Since I can't add the row built off of one table to the other table directly, I figured it was the DataRow object that was problematic, but the ItemArray property was probably all I needed.
if (isErrorRow)
{
//nr is the NewRow for dt1
var nr2 = dt2.NewRow();
nr2.ItemArray = nr.ItemArray;
dt2.Rows.Add(nr2);
}
This effectively cloned the rows.

Copying a row from one table to another using LINQ and C#

I have two tables that are pretty much exact clones of one another (identical columns, just different columns set as primary keys). Basically the second table is just for keeping a history of the first table. What I need to do is, when a user updates a record in table 1 I need to insert the original copy of that record into table 2.
I am using a LinqDataSource object and utilizing the LinqDataSource_Updating(object sender, LinqDataSourceUpdateEventArgs e) event so I have access to e.OriginalObject and that will be perfect for inserting the original row in table 2. My problem is that I don't want to have to set every property manually because there are about 50 of them, so I want to use Reflection but am not sure how to properly go about it.
Consider the following code:
INSTRUMENT_DATA_SHEET _original = (INSTRUMENT_DATA_SHEET)e.OriginalObject;
INSTRUMENT_DATA_SHEET_HISTORY _history = new INSTRUMENT_DATA_SHEET_HISTORY();
How can I go about copying all of the _original's property values to _history's? I have tried using the solution from this question, however it isn't working for me. It throws the error:
Property DATE has an incompatible type in E_and_I.INSTRUMENT_DATA_SHEET_HISTORY
My guess is that it's because the DATE column is part of the primary key in table 2, but not table 1. As I said, the only difference between the two tables are the primary keys. Here they are for your reference:
The problem I see is that your History type Date field is DateTime and your Original one is DateTime? (same problem with REV in History, it can't be null). You'll have to decide what happens if there is a null DateTime of Date in your original version. Then you should be able to modify Skeets code (oh dear!) to handle specifically these fields differently then the rest of the fields.
Ok I've managed to figure it out :) Here's what I did:
INSTRUMENT_DATA_SHEET _original = (INSTRUMENT_DATA_SHEET)e.OriginalObject;
INSTRUMENT_DATA_SHEET_HISTORY _history = new INSTRUMENT_DATA_SHEET_HISTORY();
foreach (PropertyInfo pi in _original.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
_history.GetType().GetProperty(pi.Name).SetValue(_history, pi.GetValue(_original, null), null);
}
Not very elegant but it gets the job done!

InsertAllOnSubmit only inserts one item

I am trying to use InsertAllOnSubmit to do multiple inserts, but only 1 item ever gets inserted into the table. The only reason I can think that this is happening is something to do with the generation of the Primary Key field, I am currently allowing the code to auto generate this field, and it doesn't seem to be doing that. Can anybody help?
List<rewardsClaimed> lstRewardsClaimed = new List<rewardsClaimed>();
for (int i = 0; i < ticket.delivery.quantity; i++)
{
rewardsClaimed claim = result;
lstRewardsClaimed.Add(claim);
}
dc.rewardsClaimeds.InsertAllOnSubmit(lstRewardsClaimed);
dc.SubmitChanges();
EDIT :
I have found out what the problem is....the ID field gets set to 0 by default, so that when the insert is done, since all rows have the same ID, they are treated as 1 row. How would I prevent this?
The problem is that List and Table behave completely different.
A List<T> allows you to add the same instance more than once without checking the reference in other words in your list you have multiple references to the same object.
Table<T> in the other hand when you call InsertAllOnsubmit method checks every item in the collection to see if its already "marked" to be inserted in the table. If the object its already "marked" skips it.
What is happening with your code is that you are passing the List of claims that make reference n number of times to the same object. When is passed to Table<T> the first ocurrence is marked for insertion. Since the other items in the list are the same object, they are already marked for insertion.
Hope this clarifies.
Everyone is asking to create new instance of the class RewardsClaimed. But I thought that it is not the correct reason. Hence I tried the following sample code and found that 5 different instances are added in the list.
Part 1: Showing that same item can be added to local list without creating new instance (Its not the answer)
Code:
Results:
Part 2: Creation of new primary key will be the solution. (This is the issue and solution.)
I would suggest that, please check the data in your PrimaryID Column is not repeated. By this I mean, if your primary key is not automatically generated and you generate it manually, chances are it gets rows with same primarykeys n number of times. If it is repeated then it will only insert single instance of it.
Edit: How to auto generate Field Value
If you want to auto-generate primary key refer this.
you are not creating new instance of claim.
rewardsClaimed claim = new rewardsClaimed();
List<rewardsClaimed> lstRewardsClaimed = new List<rewardsClaimed>();
for (int i = 0; i < ticket.delivery.quantity; i++)
{
rewardsClaimed claim = new rewardsClaimed();
claim.property = result.property; // do this foreach property except id field
lstRewardsClaimed.Add(claim);
}
dc.rewardsClaimeds.InsertAllOnSubmit(lstRewardsClaimed);
dc.SubmitChanges();

Linq to check if the datarow exists in a datatable

I have my query as below
DataRow dr = objDtModifier.Rows[num];
var existingRows = resultDataTable.AsEnumerable().Where(row => row == dr);
But existingRows.Count always returns me zero .
Can anyone tell what's wrong here .
You are comparing a row object from the objDtModifier source colloction with a different set of row objects in a resultDataTable collection which will alway return an empty result set as they are a different set of object references (this is regardless of whether they contain the same data or not).
Is there a property you can test against? eg:
var existingRows = resultDataTable.AsEnumerable().Where(row => row.Id == dr.Id);
It happens because row and dr not same object and your are going to compare two object,
try to check columns of row , something like primary keyvalue
You compare a row object which you get from a table called objDtModifier against a row from a table called resultDataTable. So unless that's a typo this is probably what's wrong.
Edit: Even if they contain rows from the same database table you are comparing the object references of two different row objects - this will fail. You need to compare two columns which uniquely identify the row (or maybe a set of columns).
No matter if they are same type. If objDtModifier and resultDataTable does not contain same instances the behaviour you get is correct.
row==dr uses equality by reference, like chris stated. if objDtModifier and resultDataTable contains diffrent row instances but refers to same data, you might want to use row.id==dr.id if id is the primary key of the datable.

.Net DataTable column export

Im looking to get a column and all its row data from a DataTable object then create a new column in another data table and append it with the new column and its rows. The issue I keep encountering is the row data will come out, as will the column names, but all of the rows are appended to the same column, I'm sure im missing something obvious, infact I know I am! Any help is greatly appriciated.
void GetColumns()
{
// add the columns to the new datatable
foreach (int i in mapValues)
{
SplitData.Columns.Add(i.ToString());
}
// map values contains the index numbers of my target columns
foreach (int x in mapValues)
{
foreach (DataRow row in OrigData.Rows)
{
SplitData.Rows.Add(row[mapValues[LocalIndex]]);
}
LocalIndex++;
}
}
The DataRow.Add overload that you are using is the params one, so you are just putting your orig column data in the first column of the new DataTable.
You probably want something like:
DataRow newRow = SplitData.NewRow(); // gets a new blank row with the right schema
newRow[x.ToString()] = row[mapValues[LocalIndex]; // sets the column (that you created before) to the orig data
SplitData.Rows.Add(newRow);
as the core of your second for loop. You might as well do it in one loop too.
Although the accepted answer was totally right and I learned something from it, it turns out the DataTable.ImportRow method is exactly what I want for my needs, so just for future reference for anyone who might stumble upon this.

Categories

Resources