CSLA .NET

From Rockford Lhotka's Expert C# 2008 and VB 2008 Business Objects books

"Index was outside the bounds of the array." error with CSLA 3.5 Beta 1

rated by 0 users
This post has 23 Replies | 3 Followers

Top 25 Contributor
Posts 227
triplea Posted: Sun, Mar 16 2008 6:00 PM

I finally got to play with the latest release (cslacs-3.5.0-080222.zip is the file I've got). It looks great but I stumbled upon my first problem.
I have an editable root object (Customer) which has contains an editable child object (Address). Using a Linq DAL, I fetch the Customer fields fine but when I get to the fetch part of my Address object, the first line that tries to populate a property like this:

LoadProperty<string>(HouseNumberProperty, address.HouseNumber);

fails with the following error: "Index was outside the bounds of the array." which gets caught in protected void LoadProperty<P>(PropertyInfo<P> propertyInfo, P newValue) and because in PropertyInfo.Index the index is -1. Now I checked another (very long) thread where a similar issue was reported but it seemed it happened for more complex scenarios. Mine is a straightforward one (I think).
Apologies but I am a bit new to .Net 3.5 in general so might be doing something obviously silly here...

Top 10 Contributor
Posts 500
skagen00 replied on Sun, Mar 16 2008 7:11 PM

What does your property declaration look like?

And is your class just a concrete class with no registered properties declared in any parent classes?

Top 10 Contributor
Posts 6,297
This problem is most likely caused by a bug in your RegisterProperty() call for this property. The most common issue is not getting the containing type parameter set correctly, so the property is registered with the wrong business object type.

Rocky

Top 10 Contributor
Posts 500
skagen00 replied on Mon, Mar 17 2008 10:41 AM
One of the common errors the team here makes is to leave off the "static" part of the declaration for the property, so you might look at that too.
Top 25 Contributor
Posts 227
triplea replied on Mon, Mar 17 2008 3:12 PM

Thanks to both. I was indeed using the wrong containing type parameter so I changed it and it works fine. I now begin to understand how this can be an issue with inheritance... I havent tried it yet but was there any final solution from the previous very big thread? I know its not best practice but in a lot of occasions I have something like:

Customer : BusinessBase<Customer>
GoodCustomer : Customer
BadCustomer : Customer

And use Customer to bind on a view that allows editing customers but doesnt (and shouldnt) care about the quality of the customer. That would mean that all the properties are defined in Customer but usually the validation/authorization rules are set in the conrete extended classes. Should I still register the properties in Customer with type Customer or is there a catch?

Top 10 Contributor
Posts 6,297

You can register your properties in a base class – against the base class type. That works fine.

 

The issue with inheritance is that .NET won’t necessarily initialize the static fields in your base class early enough in the process, so you need to put code in your constructor on OnDeserialized() method to set a static field (such as an integer field named _dummy or something). That forces static fields to initialize in that class and all is well.

 

Rocky

Rocky

Top 25 Contributor
Posts 227
triplea replied on Mon, Mar 17 2008 3:48 PM
Thanks, I will convert some such existing cases and see how that goes.
Top 10 Contributor
Posts 6,297
That would be very helpful - please let me know how it goes - thanks!

Rocky

Not Ranked
Posts 9
van replied on Tue, Sep 30 2008 2:24 AM

I have a problem with LoadProperty in base class (CSLA 3.5 and 3.5.1 version). I have something like this:

public abstract class BaseObject<T> : BusinessBase<T>

public abstract class BaseNameDescriptionBusinessObject<T> : BaseObject<T> where T : BaseNameDescriptionBusinessObject<T>

public class Funkcija : BaseNameDescriptionBusinessObject<Funkcija>

and exception 'Property load or set failed for property Naziv (One or more properties are not registered for this type)' appeare in BaseNameDescriptionBusinessObject<T> class when use LoadProperty<string>(NazivProperty, reader.GetString("Naziv")); I try with dummy in constructor but it didn't help.

Top 10 Contributor
Posts 6,297
Do you also set the static/Shared _dummy field in an override of OnDeserialized()?


 
----- Original Message -----
From: van
To: "rocky@lhotka.net"
Subject: Re: [CSLA .NET] "Index was outside the bounds of the array." error with CSLA 3.5 Beta 1
Date: Tue, 30 Sep 2008 07:07:31 -0500

I have a problem with LoadProperty in base class. I have like something this:

public abstract class BaseObject<T> : BusinessBase<T>

public abstract class BaseNameDescriptionBusinessObject<T> : BaseObject<T> where T : BaseNameDescriptionBusinessObject<T>

public class Funkcija : BaseNameDescriptionBusinessObject<Funkcija>

and exception 'Property load or set failed for property Naziv (One or more properties are not registered for this type)' appeare in BaseNameDescriptionBusinessObject<T> class when use LoadProperty<string>(NazivProperty, reader.GetString("Naziv")); I try with dummy in constructor but it didn't help.





Rocky

Not Ranked
Posts 9
van replied on Wed, Oct 1 2008 4:15 AM

I try with an override of OnDeserialized() now, but it doesn't solve the problem.

Maybe I have a some bug in my classes and there is a code:

// BaseObject<T> class

[Serializable]

public abstract class BaseObject<T> : BusinessBase<T>, IBusinessObjectId where T : BaseObject<T>

{

#region Constructor

protected BaseObject()

{

LoadProperty<Guid>(UidProperty, Guid.Empty);

}

#endregion

#region FactoryMethods

public static T CreateObject()

{

return DataPortal.Create<BaseObject<T>>() as T;

}

#endregion

#region DataAccess

[RunLocal()]

protected override void DataPortal_Create()

{

Uid = Guid.NewGuid();

}

#endregion

#region Properties

private static PropertyInfo<Guid> UidProperty = RegisterProperty<Guid>(typeof(T), new PropertyInfo<Guid>("Uid", "Uid"));

public Guid Uid

{

get { return GetProperty<Guid>(UidProperty); }

set { SetProperty<Guid>(UidProperty, value); }

}

public bool IsNull

{

get

{

return Uid.Equals(Guid.Empty);

}

}

#endregion

#region Methods

protected void DataFetch(NullableDataReader reader)

{

try

{

if (reader.Read())

{

LoadData(reader);

}

}

catch (Exception ex)

{

throw;

}

finally

{

if (!reader.IsClosed)

{

reader.Close();

}

}

}

protected virtual void LoadData(NullableDataReader reader)

{

try

{

LoadProperty<Guid>(UidProperty, reader.GetGuid("Uid"));

}

catch (Exception ex)

{

throw;

}

}

protected virtual void LogicalDelete(string tableName)

{

try

{

Database db = DatabaseFactory.CreateDatabase();

DbCommand cmd = db.GetStoredProcCommand("usp_LogicalDelete");

db.AddInParameter(cmd, "@tableName", DbType.String, tableName);

db.AddInParameter(cmd, "@uid", DbType.Guid, Uid);

db.ExecuteNonQuery(cmd);

}

catch (Exception ex)

{

LogHelper.LogException(ex);

throw;

}

}

#endregion

}

 

// BaseNameDescriptionBusinessObject<T>

[Serializable]

public abstract class BaseNameDescriptionBusinessObject<T> : BaseObject<T> where T : BaseNameDescriptionBusinessObject<T>

{

#region members

private static int _dummy;

#endregion

#region Constuctor

protected BaseNameDescriptionBusinessObject()

{

_dummy = 10;

}

#endregion

#region ValidationRules

protected override void AddBusinessRules()

{

AddCustomRules();

}

private void AddCustomRules()

{

ValidationRules.AddRule<T>(NazivPostoji, "Naziv");

}

private static bool NazivPostoji<T>(T target, Csla.Validation.RuleArgs e) where T : BaseNameDescriptionBusinessObject<T>

{

if (string.IsNullOrEmpty(target.Naziv))

{

e.Description = "Unesite naziv.";

return false;

}

return true;

}

#endregion

#region Property

//private static PropertyInfo<string> NazivProperty = RegisterProperty<string>(typeof(T), new PropertyInfo<string>("Naziv", "Naziv"));

//private string _naziv;

//public string Naziv

//{

// get { return GetProperty<string>(NazivProperty, _naziv); }

// set { SetProperty<string>(NazivProperty, ref _naziv, value); }

//}

//private static PropertyInfo<string> OpisProperty = RegisterProperty<string>(typeof(T), new PropertyInfo<string>("Opis", "Opis"));

//private string _opis;

//public string Opis

//{

// get { return GetProperty<string>(OpisProperty, _opis); }

// set { SetProperty<string>(OpisProperty, ref _opis, value); }

//}

private static PropertyInfo<string> NazivProperty = RegisterProperty<string>(typeof(T), new PropertyInfo<string>("Naziv", "Naziv"));

public string Naziv

{

get { return GetProperty<string>(NazivProperty); }

set { SetProperty<string>(NazivProperty, value); }

}

private static PropertyInfo<string> OpisProperty = RegisterProperty<string>(typeof(T), new PropertyInfo<string>("Opis", "Opis"));

public string Opis

{

get { return GetProperty<string>(OpisProperty); }

set { SetProperty<string>(OpisProperty, value); }

}

 

#endregion

#region Methods

protected override void LoadData(NullableDataReader reader)

{

try

{

base.LoadData(reader);

LoadProperty<string>(NazivProperty, reader.GetString("Naziv"));

LoadProperty<string>(OpisProperty, reader.GetString("Opis"));

//_naziv = reader.GetString("Naziv");

//_opis = reader.GetNullableString("Opis");

}

catch (Exception ex)

{

LogHelper.LogException(ex);

throw;

}

}

protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)

{

_dummy = 20;

base.OnDeserialized(context);

}

#endregion

}

 

// Funkcija

[Serializable]

public class Funkcija : BaseNameDescriptionBusinessObject<Funkcija>

{

#region Constructors

private Funkcija()

{

}

#endregion

#region FactoryMethods

public static Funkcija CreateChildObject()

{

return DataPortal.CreateChild<Funkcija>();

}

public static Funkcija GetFuinkcijaByUid(Guid uid)

{

return DataPortal.Fetch<Funkcija>(new SingleCriteria<Funkcija, Guid>(uid));

}

public static Funkcija GetChildByReader(NullableDataReader reader)

{

return DataPortal.FetchChild<Funkcija>(new SingleCriteria<Funkcija, NullableDataReader>(reader));

}

#endregion

#region DataAccess

private void Child_Fetch(SingleCriteria<Funkcija, NullableDataReader> criteria)

{

try

{

LoadData(criteria.Value);

}

catch (Exception ex)

{

LogHelper.LogException(ex);

throw;

}

}

private void DataPortal_Fetch(SingleCriteria<Funkcija, Guid> criteria)

{

try

{

Database db = DatabaseFactory.CreateDatabase();

DbCommand cmd = db.GetStoredProcCommand("usp_GetFuncijaByUid");

db.AddInParameter(cmd, "@uid", DbType.Guid, criteria.Value);

using (NullableDataReader reader = new NullableDataReader(db.ExecuteReader(cmd)))

{

DataFetch(reader);

}

}

catch (Exception ex)

{

throw;

}

}

protected override void Child_Create()

{

Uid = Guid.NewGuid();

ValidationRules.CheckRules();

}

private void Child_Insert()

{

DoSave();

}

private void DoSave()

{

try

{

Database db = DatabaseFactory.CreateDatabase();

DbCommand cmd = db.GetStoredProcCommand("usp_FunkcijaInsertUpdate");

db.AddInParameter(cmd, "@uid", DbType.Guid, Uid);

db.AddInParameter(cmd, "@naziv", DbType.String, Naziv);

db.AddInParameter(cmd, "@opis", DbType.String, Opis);

db.AddInParameter(cmd, "@isNew", DbType.Boolean, IsNew);

db.ExecuteNonQuery(cmd);

}

catch (Exception ex)

{

LogHelper.LogException(ex);

throw;

}

}

private void Child_Update()

{

DoSave();

}

private void Child_DeleteSelf()

{

LogicalDelete("Funkcije");

}

#endregion

}

 

Is there I'm doing something wrong?

Top 75 Contributor
Posts 95
stefan replied on Wed, Oct 1 2008 4:28 AM
Hi van,

van:

// BaseObject<T> class

[Serializable]

public abstract class BaseObject<T> : BusinessBase<T>, IBusinessObjectId where T : BaseObject<T>

{

#region Constructor

protected BaseObject()

{

LoadProperty<Guid>(UidProperty, Guid.Empty);

}

#endregion

...

Is there I doing something wrong?


Yes! Look at your constructor - missing something thereWink [;)]

Read this:  http://forums.lhotka.net/forums/post/26436.aspx


Stefan
Not Ranked
Posts 9
van replied on Thu, Oct 2 2008 2:25 AM

I added static field and an override of OnDeserialized() and I now have:

// BaseObject class

private static int _forceInit;

#region Constructor

protected BaseObject()

{

_forceInit = 5;

LoadProperty<Guid>(UidProperty, Guid.Empty);

}

protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)

{

_forceInit = 10;

}

 

// BaseNameDescriptionBusinessObject class

private static int _dummy;

#region Constuctor

protected BaseNameDescriptionBusinessObject()

{

_dummy = 10;

}

protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)

{

_dummy = 20;

}

 

//  Funkcija class

private static int _forceInit;

#region Constructors

private Funkcija()

{

_forceInit = 10;

}

protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)

{

_forceInit = 15;

}

 

and problem still exist. Properties in the BaseObject and Funkcija classes registered properly and there is not a problem, but property Naziv and Opis in the BaseNameDescriptionBusinessObject never registered. When I go through debug, lines

private static PropertyInfo<string> NazivProperty = RegisterProperty<string>(typeof(T), new PropertyInfo<string>("Naziv", "Naziv"));

and

private static PropertyInfo<string> OpisProperty = RegisterProperty<string>(typeof(T), new PropertyInfo<string>("Opis", "Opis"));

executed before

protected override void LoadData(NullableDataReader reader)

{

try

{

base.LoadData(reader);

LoadProperty<string>(NazivProperty, reader.GetString("Naziv"));

LoadProperty<string>(OpisProperty, reader.GetString("Opis"));

//_naziv = reader.GetString("Naziv");

//_opis = reader.GetNullableString("Opis");

}

catch (Exception ex)

{

LogHelper.LogException(ex);

throw;

}

}

 

but it's throw an exception 'Property load or set failed for property Naziv (One or more properties are not registered for this type)'

Top 10 Contributor
Posts 6,297

The _forceInit code looks right. You have it in EVERY class? Base and sub?

 

Rocky

Rocky

Not Ranked
Posts 9
van replied on Fri, Oct 3 2008 2:27 AM
Yes, I know but stefan wrote that I missing something in BaseObject class. He meaned that I haven't _forceInit in this class. I readed your post at link  http://forums.lhotka.net/forums/post/26436.aspx and I know that it is not need in BaseObject class, because inherited directly from BusinessBase<T>, but I try _forceInit in every class. Is it mean that my classes in second post are good and changes don't need? There is a _dummy only in BaseNameDescriptionBusinessObject.
Page 1 of 2 (24 items) 1 2 Next > | RSS

Please contact Magenic for your .NET consulting
and CSLA .NET mentoring needs.
Please consider making a donation to help support the ongoing development of CSLA .NET.

Make donation through PayPal - it's fast, free and secure!
Why donate?
Copyright (c) 2006-2010 Marimer LLC. All rights reserved.
Email admin@lhotka.net for support.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems