Tech Off Thread

7 posts

Typed Datasets - GetChildRows (Bug or am I doing something wrong?)

Back to Forum: Tech Off
  • User profile image
    Gidion2k4

    Hi everybody!

    I've stumbled across a funny behaviour of a typed dataset in a new application of mine. Some how the generated code gives me a Invalid Cast Exception.

    I've reproduced the behaviour as follows.
    I've created a database "test160106", I've created the table "Parent" with two columns (column 1: ID int, column 2: nvarchar name) and a table "Child" with three columns (column 1: ID int, column 2: nvarchar name, column 3: int ParentID). I also added the relation between ParentID and Parent table.)

    I added a new data connection pointing to this database and let it create my datasets.

    Now I use the following code that should me give me all child rows belonging to a parent.

    test160106DataSetTableAdapters.ParentTableAdapter _pta = new Test160106.test160106DataSetTableAdapters.ParentTableAdapter();

    foreach (test160106DataSet.ChildRow _childRow in _pta.GetData().FindByID(1).GetChildRows())

    {

    Console.Write(String.Format("{0}: {1}", _childRow.ID, _childRow.Name));

    }

    Console.ReadLine();

    When executing this code, it gives me an Invalid Cast Exception (Unable to cast object of type 'ParentRow[]' to type 'ChildRow[]'.), which comes from the generated code:

    [System.Diagnostics.DebuggerNonUserCodeAttribute()]

    public ChildRow[] GetChildRows() {

    return ((ChildRow[])(base.GetChildRows(this.Table.ChildRelations["FK_Child_Parent"])));

    }


    Can anyone reproduce this? If so, is it a bug or am I doing someting I shouldn't be?

    Any help appreciated.

  • User profile image
    paulrec

    I am having the exact same problem.  Did you ever find a fix for this?

    Alternatively, I am trying to execute GetChildRows() explicity by providing the relation name, but I always get 0 rows returned.  This is pretty frustrating.

    Anyone else out there with this issue?

  • User profile image
    Gidion2k4

    Nope, still no answer. I thought about posting to one of the Newsgroups, but I haven't got round to doing that yet.

  • User profile image
    steveculshaw

    Yeap, I've just hit this problem   Perplexed

    Glad it's not just me, but frustrated that there is a problem 

    Any luck in finding a fix ?


    Cheers,
    Steve C.

  • User profile image
    PerfectPhase

    For the relations to work you MUST have a Dataset object constructed.

    By using the GetData() method of the Table adapter you get only a DataTable not a full Dataset.  for example if you did

    TestDs.ParentDataTable dt = taPar.GetData () ;

    and then checked dt's DataSet propery you would find it's null.

    The way around it is to do...

    testDSTableAdapters.parentTableAdapter ta = new ParentChild.testDSTableAdapters.parentTableAdapter();
    testDSTableAdapters.ChildTableAdapter cta = new ParentChild.testDSTableAdapters.ChildTableAdapter();
    testDS ds = new testDS() ;
    cta.Fill(ds.Child);
    ta.Fill(ds.parent);
    testDS.parentRow pr = ds.parent.FindByID(1);
    testDS.ChildRow[] cra = pr.GetChildRows();
    etc....

    Also you MUST fill the child table before your call to GetChildRows, the TableAdapter will not go to the database for you.

    Stephen.

    P.S. The reason for the strange error is that deep down in DataRow.GetChildRows it is expecting a DataRelation to be passed in, as the DataSet is null and the releation can't be found, it constructs an array to return based on it's own type which is parent.

    public DataRow[] GetChildRows(DataRelation relation, DataRowVersion version)
    {
          if (relation == null)
          {
                return this._table.NewRowArray(0);
          }
          etc.....
    }

    protected internal DataRow[] NewRowArray(int size)
    {
          if (this.IsTypedDataTable)
          {
                if (size != 0)
                {
                      return (DataRow[]) Array.CreateInstance(this.GetRowType(), size);
                }
                if (this.EmptyDataRowArray == null)
                {
                      this.EmptyDataRowArray = (DataRow[]) Array.CreateInstance(this.GetRowType(), 0);
                }
                return this.EmptyDataRowArray;
    etc...

    Which finally chokes on the following in the typed dataset's generated code

    public ChildRow[] GetChildRows()
    {
         return ((ChildRow[])(base.GetChildRows(this.Table.ChildRelations["parent_Child"])));
    }

    Not sure if this was a better idea than returning a null?

  • User profile image
    bluebunny

    PerfectPhase wrote:
    For the relations to work you MUST have a Dataset object constructed.

    By using the GetData() method of the Table adapter you get only a DataTable not a full Dataset.  for example if you did

    TestDs.ParentDataTable dt = taPar.GetData () ;

    and then checked dt's DataSet propery you would find it's null.


    Thank you, thank you!

    Would have wasted the afternoon trying to figure this out myself.

    Greg

  • User profile image
    efosshaug

    PerfectPhase said:
    For the relations to work you MUST have a Dataset object constructed.

    By using the GetData() method of the Table adapter you get only a DataTable not a full Dataset.  for example if you did

    TestDs.ParentDataTable dt = taPar.GetData () ;

    and then checked dt's DataSet propery you would find it's null.

    The way around it is to do...

    testDSTableAdapters.parentTableAdapter ta = new ParentChild.testDSTableAdapters.parentTableAdapter();
    testDSTableAdapters.ChildTableAdapter cta = new ParentChild.testDSTableAdapters.ChildTableAdapter();
    testDS ds = new testDS() ;
    cta.Fill(ds.Child);
    ta.Fill(ds.parent);
    testDS.parentRow pr = ds.parent.FindByID(1);
    testDS.ChildRow[] cra = pr.GetChildRows();
    etc....

    Also you MUST fill the child table before your call to GetChildRows, the TableAdapter will not go to the database for you.

    Stephen.

    P.S. The reason for the strange error is that deep down in DataRow.GetChildRows it is expecting a DataRelation to be passed in, as the DataSet is null and the releation can't be found, it constructs an array to return based on it's own type which is parent.

    public DataRow[] GetChildRows(DataRelation relation, DataRowVersion version)
    {
          if (relation == null)
          {
                return this._table.NewRowArray(0);
          }
          etc.....
    }

    protected internal DataRow[] NewRowArray(int size)
    {
          if (this.IsTypedDataTable)
          {
                if (size != 0)
                {
                      return (DataRow[]) Array.CreateInstance(this.GetRowType(), size);
                }
                if (this.EmptyDataRowArray == null)
                {
                      this.EmptyDataRowArray = (DataRow[]) Array.CreateInstance(this.GetRowType(), 0);
                }
                return this.EmptyDataRowArray;
    etc...

    Which finally chokes on the following in the typed dataset's generated code

    public ChildRow[] GetChildRows()
    {
         return ((ChildRow[])(base.GetChildRows(this.Table.ChildRelations["parent_Child"])));
    }

    Not sure if this was a better idea than returning a null?

    Thanks .
    This really saved my day!

    Espen

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.