Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

This row already belongs to another table."

When you try to add a DataRow from one table to another, you may encounter the following error message:

"This row already belongs to another table."

This error message appears if you try to add (copy) a DataRow from table1 to table2, for example, with the following C# code:

table2.Rows.Add(row);

where row is a DataRow object from table1.

To successfully copy the row, you'll need to use ImportRow() method:

table2.ImportRow(row);

Don't forget to define a proper value of column number for table2 first or no data will be displayed if you bind table2 with a gridview, for example.

Customize DataRow to keep an object

To enable a DataRow to keep a custom object, create a new class inheriting DataRow class.
The code below shows how to keep an object of a custom class named "VideoGame".
 
#region Custom DataRow
pubilc class VideoGameDataRow : DataRow{
        private VideoGame vdoGame;
        public VideoGameDataRow(DataRowBuilder rowBuilder) : base(rowBuilder)
                // Default constructor.
        }
        public VideoGame GameObject{
                set { vdoGame = value; }
                get { return vdoGame; }
        }
}
#endregion
 
You will also need a custom DataTable to handle this custom DataRow since the default DataTable can take only the default DataRow.
Override the NewRow method (NewRowBuilder()) to handle the custom DataRow.
 
#region Custom DataTable
public class VideoGameTable : DataTable{
        protected override DataRow NewRowBuilder(DataRowBuilder builder){
                return new VideoGameDataRow(builder);
        }
}
#endregion
 
When used, cast a created row as the custom DataRow.
 
#region Usage
...
        VideoGame game = new VideoGame();
        VideoGameDataTable vdoGameTable = new VideoGameDataTable();
        VideoGameDataRow newGameRow = (VideoGameDataRow)(vdoGameTable.NewRow());
        newGameRow.GameObject = game;
...
#endregion
 
Note that you cannot create a new DataRow using the new keyword (DataRow row = new DataRow();).
This will generate an error saying that DataRow(DataRowBuilder) is inaccessible due to its protection level.
This applies to a custom DataRow which inherits from DataRow as well.
 
 

Reading XmlDocument which has a namespace

The scenario is I was trying to read a response message from Amazon AWS which contains a namespace using VS2008/C#.
A sample document can be found here.
Let's assume that the response message has been saved as ItemLookupResponse.xml.
I tried the following code to get the number of elements in the document.
Counted manually, the total number of elements is 10.
XmlDocument xDoc = new XmlDocument();
xDoc.Load("resources/ItemLookupResponse.xml");
XmlNodeList offerNodes = xDoc.SelectNodes("//Offer");
return offerNodes.Count;
Guess what you would get as the returned integer...
Well... I expected 10.
But it turned out to be 0!
After doing some researches, I found that
If the XML includes a default namespace, XmlNamespaceManager must be used and a prefix and namespace URI must be added to it.
Therefore, my code has been modified to be as followed:
XmlDocument xDoc = new XmlDocument();
xDoc.Load("resources/ItemLookupResponse.xml");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xDoc.NameTable);
// get the document's default namespace URI.
nsMgr.AddNamespace("aws", xDoc.DocumentElement.NamespaceURI); 
XmlNodeList offerNodes = xDoc.SelectNodes("//aws:Offer", nsMgr);
return offerNodes.Count;
Now it returns 10 as expected. Sweet~
Notice that the defined prefix is needed in the XPath expression (//aws:Offer).