Bug in FetchChild / method caller

Bug in FetchChild / method caller

Old forum URL: forums.lhotka.net/forums/t/10639.aspx


xal posted on Thursday, August 25, 2011

I have a child collection that loads from an array. Particularly, a DataRow array.

When the datarow array's length is 0, Child_Fetch gets a null reference.

Example:

class Class1 : Csla.BusinessBase<Class1>
  {
    void Child_Fetch(DataRow[] p)
    { Console.WriteLine(p == null); }
  }

 

So when you do this:

Csla.DataPortal.FetchChild<Class1>(new DataRow[] { });

The expected result is to get an empty datarow array in Child_Fetch.

 

The problem is that if you call FetchChild() without passing any parameter, the method gets an empty object array anyway instead of null.

 

This could be solved by creating overloads for FetchChild (and the other methods) that don't take any param array and can pass null instead of an empty object[] down the pipeline.

 

Ideas?

Cheers,

Andrés

 

RockfordLhotka replied on Thursday, August 25, 2011

This is a known issue, and it is (to my knowledge) unsolvable.

The problem is that, at runtime, we don't have enough information to differentiate between an array, the param array, and a null value. The end result is that at least one scenario can't be made to work:

I've spent many, many hours on this without finding a solution. I think Blake spent a bunch of time on this too, as did Justin at one point.

If you can solve it, I'd love to see the answer. :)

xal replied on Thursday, August 25, 2011

Hi Rocky!

Thanks for your reply. I was able to make those changes successfully.

Tested with these calls:

        Csla.DataPortal.FetchChild<Class1>();
        Csla.DataPortal.FetchChild<Class1>(1);
        Csla.DataPortal.FetchChild<Class1>(1, 2);
        Csla.DataPortal.FetchChild<Class1>(null);
        Csla.DataPortal.FetchChild<Class1>(new int[] { });
        Csla.DataPortal.FetchChild<Class1>(new int[] { 0 });
        Csla.DataPortal.FetchChild<Class2>(null);
        Csla.DataPortal.FetchChild<Class2>(new object());
        Csla.DataPortal.FetchChild<Class2>("");
        Csla.DataPortal.FetchChild<Class2>(new Class2());

Against these objects:

  class Class1 : Csla.BusinessBase<Class1>
  {
    void Child_Fetch(int[] p)
    { Console.WriteLine(p == null); }
    void Child_Fetch(int a)
    { Console.WriteLine("{0}", a); }
    void Child_Fetch(int a, int b)
    { Console.WriteLine("{0}, {1}", a, b); }
    void Child_Fetch()
    { Console.WriteLine("parameterless"); }
  }
  class Class2 : Csla.BusinessBase<Class1>
  {
    void Child_Fetch(object p)
    { Console.WriteLine("object overload. IsNull = {0}", p == null); }

    void Child_Fetch(string p)
    { Console.WriteLine("String overload. IsNull = {0}", p == null); }
  }

 

The fix involves mostly adding overloads to indicate whether an argument has been explicitly passed or not, such as this:

    private object Fetch(Type objectType, bool hasParameters, params object[] parameters)

    public object Fetch(Type objectType, params object[] parameters)
    {
      return Fetch(objectType, true, parameters);
    }
    public object Fetch(Type objectType)
    {
      return Fetch(objectType, false, null);
    }

I will forward this changes to you by email.

 

Cheers

Copyright (c) Marimer LLC