Child list is intermittently null

Child list is intermittently null

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


BarryC posted on Monday, March 23, 2009

I am getting a strange intermittent error when testing one of my business objects with NUnit. 

The Template business object has two editable child Lists: NotificationList and SignOffList.  Sometimes when a new Template object is created these child lists are null instead of a new empty list.  However, this only happens intermittently.  Other times, the tests will run fine.

Does anybody have any ideas what might be causing this?  I am using Csla 3.6.0.

 

using System;

using System.Linq;

using Csla;

using Csla.Data;

using Csla.Security;

using Csla.Validation;

namespace Templates

{

[Serializable()]

public partial class Template : Csla.BusinessBase<Template>

{

#region Business Properties and Methods

// Register properties

private static PropertyInfo<int> IDProperty = RegisterProperty<int>(typeof(Template), new PropertyInfo<int>("Id"));

private static PropertyInfo<string> NameProperty = RegisterProperty<string>(typeof(Template), new PropertyInfo<string>("Name"));

private static PropertyInfo<int> GroupIDProperty = RegisterProperty<int>(typeof(Template), new PropertyInfo<int>("GroupID"));

private static PropertyInfo<string> DescriptionProperty = RegisterProperty<string>(typeof(Template), new PropertyInfo<string>("Description"));

private static PropertyInfo<LockInfoList> LockInfoListProperty = RegisterProperty<LockInfoList>(typeof(LockInfoList), new PropertyInfo<LockInfoList>("LockInfoList"));

private static PropertyInfo<NotificationList> NotificationListProperty = RegisterProperty<NotificationList>(typeof(Template), new PropertyInfo<NotificationList>("NotificationList"));

private static PropertyInfo<SignOffList> SignOffListProperty = RegisterProperty<SignOffList>(typeof(Template), new PropertyInfo<SignOffList>("SignOffList"));

private byte[] _lastChanged;

[System.ComponentModel.DataObjectField(true, true)]

public int ID

{

get { return GetProperty<int>(IDProperty); }

}

public string Name

{

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

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

}

public int GroupID

{

get { return GetProperty<int>(GroupIDProperty); }

set { SetProperty<int>(GroupIDProperty, value); }

}

public string Description

{

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

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

}

// Child properties

public NotificationList NotificationList

{

get

{

if (!FieldManager.FieldExists(NotificationListProperty))

LoadProperty<NotificationList>(NotificationListProperty, NotificationList.NewNotificationList());

return GetProperty<NotificationList>(NotificationListProperty);

}

}

public SignOffList SignOffList

{

get

{

if (!FieldManager.FieldExists(SignOffListProperty))

LoadProperty<SignOffList>(SignOffListProperty, SignOffList.NewSignOffList());

return GetProperty<SignOffList>(SignOffListProperty);

}

}

public LockInfoList LockInfoList

{

get

{

if (!FieldManager.FieldExists(LockInfoListProperty))

LoadProperty<LockInfoList>(LockInfoListProperty, LockInfoList.NewLockInfoList());

return GetProperty<LockInfoList>(LockInfoListProperty);

}

}

#endregion //Business Properties and Methods

#region Validation Rules

protected override void AddBusinessRules()

{

//

// Name

//

ValidationRules.AddRule(CommonRules.StringRequired, NameProperty);

ValidationRules.AddRule(CommonRules.StringMaxLength, new CommonRules.MaxLengthRuleArgs(NameProperty, 50));

//

// Description

//

ValidationRules.AddRule(CommonRules.StringMaxLength, new CommonRules.MaxLengthRuleArgs(DescriptionProperty, 255));

AddCustomRules();

}

partial void AddCustomRules();

#endregion //Validation Rules

#region Factory Methods

public static Template NewTemplate()

{

return DataPortal.Create<Template>();

}

public static Template GetTemplate(int id)

{

return DataPortal.Fetch<Template>(new SingleCriteria<Template, int>(id));

}

public static void DeleteTemplate(int id)

{

DataPortal.Delete(new SingleCriteria<Template, int>(id));

}

private Template()

{ /* require use of factory method */ }

#endregion //Factory Methods

#region Data Access

#region Data Access - Create

[RunLocal]

protected override void DataPortal_Create()

{

bool cancel = false;

OnCreating(ref cancel);

if (cancel) return;

ValidationRules.CheckRules();

OnCreated();

}

partial void OnCreating(ref bool cancel);

partial void OnCreated();

#endregion //Data Access - Create

#region Data Access - Fetch

private void DataPortal_Fetch(SingleCriteria<Template, int> criteria)

{

bool cancel = false;

OnFetching(criteria, ref cancel);

if (cancel) return;

using (var mgr = ContextManager<Pulse.PLMSuite.DalLinq.PulseDbDataContext>

.GetManager(Database.PulseDb))

{

//set option to eager load child object(s)

var opts = new System.Data.Linq.DataLoadOptions();

opts.LoadWith<Pulse.PLMSuite.DalLinq.claims_templates_Template>(p => p.NotificationList);

opts.LoadWith<Pulse.PLMSuite.DalLinq.claims_templates_Template>(p => p.SignOffList);

mgr.DataContext.LoadOptions = opts;

var data = mgr.DataContext.claims_templates_Template

.Single(r => r.ID == criteria.Value);

OnMemberLoading(data);

LoadProperty<int>(IDProperty, data.ID);

LoadProperty<string>(NameProperty, data.Name);

LoadProperty<int>(GroupIDProperty, data.GroupID);

LoadProperty<string>(DescriptionProperty, data.Description);

_lastChanged = data.LastChanged.ToArray();

//Load child object(s)

LoadProperty<NotificationList>(NotificationListProperty, NotificationList.GetNotificationList(data.NotificationList));

LoadProperty<SignOffList>(SignOffListProperty, SignOffList.GetSignOffList(data.SignOffList));

OnMemberLoaded();

ValidationRules.CheckRules();

}//using

OnFetched();

}

partial void OnFetching(SingleCriteria<Template, int> criteria, ref bool cancel);

partial void OnFetched();

partial void OnMemberLoading(Pulse.PLMSuite.DalLinq.claims_templates_Template data);

partial void OnMemberLoaded();

#endregion //Data Access - Fetch

#region Data Access - Insert

protected override void DataPortal_Insert()

{

bool cancel = false;

OnInserting(ref cancel);

if (cancel) return;

using (var mgr = ContextManager<Pulse.PLMSuite.DalLinq.PulseDbDataContext>

.GetManager(Database.PulseDb))

{

// Check that no template with this name already exists.

if (Template.Exists(this.Name))

throw new Exceptions.UniqueConstraintException(string.Format("Unable to save template. A template named {0} already exists.", this.Name));

 

var data = new Pulse.PLMSuite.DalLinq.claims_templates_Template();

OnMemberReading(data);

data.Name = ReadProperty<string>(NameProperty);

data.GroupID = ReadProperty<int>(GroupIDProperty);

data.Description = ReadProperty<string>(DescriptionProperty);

OnMemberRead();

mgr.DataContext.claims_templates_Template.InsertOnSubmit(data);

mgr.DataContext.SubmitChanges();

LoadProperty<int>(IDProperty, data.ID);

_lastChanged = data.LastChanged.ToArray();

//Insert Child object(s)

DataPortal.UpdateChild(ReadProperty<NotificationList>(NotificationListProperty), this);

DataPortal.UpdateChild(ReadProperty<SignOffList>(SignOffListProperty), this);

}//using

OnInserted();

}

partial void OnInserting(ref bool cancel);

partial void OnInserted();

partial void OnMemberReading(Pulse.PLMSuite.DalLinq.claims_templates_Template data);

partial void OnMemberRead();

#endregion //Data Access - Insert

#region Data Access - Update

protected override void DataPortal_Update()

{

bool cancel = false;

OnUpdating(ref cancel);

if (cancel) return;

using (var mgr = ContextManager<Pulse.PLMSuite.DalLinq.PulseDbDataContext>

.GetManager(Database.PulseDb))

{

var data = new Pulse.PLMSuite.DalLinq.claims_templates_Template()

{

ID = ReadProperty<int>(IDProperty)

};

data.LastChanged = _lastChanged;

mgr.DataContext.claims_templates_Template.Attach(data);

OnMemberReading(data);

if (IsSelfDirty)

{

data.Name = ReadProperty<string>(NameProperty);

data.GroupID = ReadProperty<int>(GroupIDProperty);

data.Description = ReadProperty<string>(DescriptionProperty);

}

//Update Child object(s)

DataPortal.UpdateChild(ReadProperty<NotificationList>(NotificationListProperty), this);

DataPortal.UpdateChild(ReadProperty<SignOffList>(SignOffListProperty), this);

OnMemberRead();

mgr.DataContext.SubmitChanges();

if (IsSelfDirty)

{

LoadProperty<int>(IDProperty, data.ID);

_lastChanged = data.LastChanged.ToArray();

}

}//using

OnUpdated();

}

partial void OnUpdating(ref bool cancel);

partial void OnUpdated();

#endregion //Data Access - Update

#region Data Access - Delete

protected override void DataPortal_DeleteSelf()

{

bool cancel = false;

OnSelfDeleting(ref cancel);

if (cancel) return;

using (var mgr = ContextManager<Pulse.PLMSuite.DalLinq.PulseDbDataContext>

.GetManager(Database.PulseDb))

{

OnMemberSelfDeleting();

//Delete Child object(s), which may contain concurrency check

NotificationList.Clear();

DataPortal.UpdateChild(ReadProperty<NotificationList>(NotificationListProperty), this);

SignOffList.Clear();

DataPortal.UpdateChild(ReadProperty<SignOffList>(SignOffListProperty), this);

var data = new Pulse.PLMSuite.DalLinq.claims_templates_Template()

{

ID = ReadProperty<int>(IDProperty)

};

data.LastChanged = _lastChanged;

mgr.DataContext.claims_templates_Template.Attach(data);

mgr.DataContext.claims_templates_Template.DeleteOnSubmit(data);

OnMemberSelfDeleted();

mgr.DataContext.SubmitChanges();

}//using

SetProperty<NotificationList>(NotificationListProperty, NotificationList.NewNotificationList());

SetProperty<SignOffList>(SignOffListProperty, SignOffList.NewSignOffList());

OnSelfDeleted();

}

partial void OnSelfDeleting(ref bool cancel);

partial void OnSelfDeleted();

partial void OnMemberSelfDeleting();

partial void OnMemberSelfDeleted();

private void DataPortal_Delete(SingleCriteria<Template, int> criteria)

{

bool cancel = false;

OnDeleting(criteria, ref cancel);

if (cancel) return;

using (var mgr = ContextManager<Pulse.PLMSuite.DalLinq.PulseDbDataContext>

.GetManager(Database.PulseDb))

{

var data = mgr.DataContext.claims_templates_Template

.Single(r => r.ID == criteria.Value);

OnMemberDeleting(data);

//Delete Child object(s)

mgr.DataContext.claims_templates_Notification.DeleteAllOnSubmit(data.NotificationList);

mgr.DataContext.claims_templates_SignOff.DeleteAllOnSubmit(data.SignOffList);

mgr.DataContext.claims_templates_Template.DeleteOnSubmit(data);

OnMemberDeleted();

mgr.DataContext.SubmitChanges();

}//using

SetProperty<NotificationList>(NotificationListProperty, NotificationList.NewNotificationList());

SetProperty<SignOffList>(SignOffListProperty, SignOffList.NewSignOffList());

OnDeleted();

}

partial void OnDeleting(SingleCriteria<Template, int> criteria, ref bool cancel);

partial void OnDeleted();

partial void OnMemberDeleting(Pulse.PLMSuite.DalLinq.claims_templates_Template data);

partial void OnMemberDeleted();

#endregion //Data Access - Delete

#endregion //Data Access

}

}

 

 

 

 

Michael replied on Tuesday, March 24, 2009

Hi Barry

I faced a similar problem recently with regards to lazy-loaded child lists and nunit tests. The solution for me was to first check if the child list has in fact been loaded before attempting to insert or update the object, as follows:

if (FieldManager.FieldExists(
NotificationListProperty))
  DataPortal.UpdateChild(ReadProperty<NotificationList>(NotificationListProperty), this);

if (FieldManager.FieldExists(SignOffListProperty))
  DataPortal
.UpdateChild(ReadProperty<SignOffList>(SignOffListProperty), this);

For more info see: http://forums.lhotka.net/forums/thread/30103.aspx

Regards
Michael


Copyright (c) Marimer LLC