p 145 (BusinessListBase)
The code in the download differs from the book for the RemoveItem() method in the last code block.
Unfortunately it turns out the neither the book code nor 2.0 download code provides the complete answer, because the eventing issue has a number of odd twists and turns based on whether you serialize your objects or not (through Clone() or using a remote data portal).
The current version: 2.1.4 (www.lhotka.net/cslanet/download.aspx) is pretty close, but even that has an issue with deserialized objects. I believe I have all of it correct now in what will become version 3.0.
The code in the book works if you never serialize objects.
But if you serialize/deserialize your objects then the automatic event handling provided by BindingList<T> gets lost, and so it is necessary to manually rehook those events and handle them properly. Somehow part of that code got into the download, though none of it is covered in Chapter 3 - so the errata is virtually impossible to work back into the book at this point :(
However, if you search through BusinessListBase for PropertyChanged you'll find where the events are hooked and where they are used. In RemoveItem() they must be unhooked, because there's no need to process the events from deleted objects.
If you look at 2.1.4 things are quite a bit different yet, because I'm being more proactive about checking to see if the child object implements INotifyPropertyChanged. In 2.0 I pre-suppose that to be true, but in 2.1+ I loosened the rules for what can be a child object, so that assumption was no longer true.
The only thing left, which I address in 3.0, is that the changed property's PropertyDescriptor should be passed up through the ListChanged event when it is raised. So in 3.0 there's now code to find and include the PropertyDescriptor. Here's a link to the current BLB class in the repository:
http://www.lhotka.net/cslacvs/viewvc.cgi/trunk/cslacs/Csla/BusinessListBase.cs?view=markup
(Updated 4/12/2007)
View
|
p 200 (Csla.DataPortalClient.EnterpriseServicesProxy)
Chapter 4, Page 200, Third paragraph from bottom of page
Text
"Notice the try...catch block ..."
should read
"Notice the try...finally block ..."
(Updated 1/26/2007)
View
|
p 427
The last line of the code block at the top of the page should read:
_timestamp = (byte[])cm.Parameters["@newLastChanged"].Value;
(Updated 1/26/2007)
View
|
p 440 (Validation Rules)
In the second code block on the page, the second line from the bottom of the code reads:
}""
It should read:
}
(Updated 12/1/2006)
View
|
p107, 109 (n-level undo)
Several places on these pages the term "HashTable" is used. This should be replaced with the term "HybridDictionary".
(Updated 12/1/2006)
View
|
p 61 (BusinessListBase)
In the Note section near the bottom of the page the first word in the note is "BusinessListBaseBusinessListBase". This should read "BusinessListBase".
(Updated 12/1/2006)
View
|
p 109 (UndoChanges)
In the first sentence of the second paragraph the term "Csla.Core.IEditableObject" should be replaced with the term "IUndoableObject".
(Updated 12/1/2006)
View
|
p 104 (CopyState)
On line 33 in the code block the line:
((Core.IEditableObject)value).CopyState();
should read:
((Core.IUndoableObject)value).CopyState();
(Updated 12/1/2006)
View
|
p 353 (addAssignment)
In the first code block on the page, the first four lines should read:
CREATE PROCEDURE addAssignment ( @projectId uniqueidentifier, @resourceId int,
(Updated 9/27/2006)
View
|
p 70 (data portal)
In the second paragraph under the Data Portal heading the first sentence should read:
As you'll see in Chapter 8, business objects will encapsulate data access logic within the objects.
(Updated 9/7/2006)
View
|
p 68 (property implementation)
In the code block there's a missing close bracket (}) in the set block, immediately before the else statement:
} }
else
throw new ...
This bracket should be line 20 in the code listing.
(Updated 8/31/2006)
View
|
p 178 (Figure 4-8)
The decision box "Parameters all null or type object?" directs to the wrong boxes.
Swap the "Yes" and "No" labels on the outbound arrows from the decision box.
(Updated 8/30/2006)
View
|
p 389 (switchable template)
The GetSwitchableRoot() method is incorrect, and should call DataPortal.Fetch. The code on the page is:
public static SwitchableObject GetSwitchableRoot(int id) { return DataPortal.Create<SwitchableObject>( new RootCriteria(id)); } and should be:
public static SwitchableObject GetSwitchableRoot(int id) { return DataPortal.Fetch<SwitchableObject>( new RootCriteria(id)); }
(Updated 8/12/2006)
View
|
p 491 (RolesEdit)
In the code at the end of the page, the finally block is missing a line and should read:
finally
{
this.rolesBindingSource.RaiseListChangedEvents = true;
this.rolesBindingSource.ResetBindings(false);
}
(Updated 6/6/2006)
View
|
p 491 (RolesEdit)
The first few lines of the code block at the bottom of the page are incorrect. The proper way to tell data binding that you are done editing is to call EndEdit() on the binding source control, not to call ApplyEdit() manually.
The first 9 lines of the code in the book should be replaced by the following 10 lines:
private void SaveButton_Click(object sender, EventArgs e)
{
this.rolesBindingSource.RaiseListChangedEvents = false;
this.rolesBindingSource.EndEdit();
try
{
Roles temp = _roles.Clone();
_roles = temp.Save();
this.Close();
}
(Updated 6/6/2006)
View
|
p 402 (name/value list objects)
In the code block in the middle of the page the line beginning with "return =" is incorrect. Remove the "=" from that line.
(Updated 6/5/2006)
View
|
p 266 (SmartDate)
The first line in the code block at the bottom of the page is missing a (. It should read:
public static DateTime StringToDate(string value)
(Updated 5/31/2006)
View
|
p 48 (Fig 2-4)
"MyObjectobj" should read "MyObject obj"
(Updated 5/18/2006)
View
|
p 449 (ResourceList)
In the code block at the top of the page, IsReadOnly is set to false twice. The second time it should be set to true:
IsReadOnly = true;
(Updated 5/3/2006)
View
|
p 539 (html comment)
At the top of the page there is a "comment" in the HTML that is incorrect:
<%-- page content goes here --%>
This should be replaced by
<!-- page content goes here -->
(Updated 4/20/2006)
View
|
p 129 (example code)
In the code example at the top of the page, "If" should not be capitalized and the conditional is missing a close ")". The line should read:
if (string.IsNullOrEmpty(((Customer)target).Name))
(Updated 4/16/2006)
View
|
p 147 (Figure 3-4)
In the right-most part of the figure in "After col.CancelEdit()" the figure should show DEL=false, not DEL=true.
(Updated 4/13/2006)
View
|
p 282 (Utilities.GetPropertyType)
The Utilities.GetPropertyType() method has an incorrect check for Nullable<T>. The correct code in the code block in the middle of the page should be:
public static Type GetPropertyType(Type propertyType)
{
Type type = propertyType;
if (type.IsGenericType &&
(type.GetGenericTypeDefinition() == typeof(Nullable<>)))
return type.GetGenericArguments()[0];
return type;
}
Note the missing <> after the word Nullable on line 5.
(Updated 4/11/2006)
View
|
p 318 (ObjectFieldInfo.Nullable)
The ObjectFieldInfo.Nullable() method has an incorrect check for Nullable<T>. The correct code at the top of the page should be:
if (!t.IsValueType || _isNullable)
return true;
if (t.IsGenericType)
return (t.GetGenericTypeDefinition() == typeof(Nullable<>));
return false;
}
}
Note the missing <> after the word Nullable on line 4.
(Updated 4/11/2006)
View
|
p 351 (addProject/updateProject stored procedures)
The addProject stored procedure (code block at the top of the page) has @description declared twice. Only the varchar(MAX) declaration should be present:
@description varchar(MAX),
The updateProject stored procedure (code block at the bottom of the page) has @lastChanged declared twice. It should only be declared once:
@lastChanged timestamp,
(Updated 4/10/2006)
View
|
p 109 (UndoableBase)
The Csla.Core.UndoableBase.AcceptChanges() method is missing a type check:
foreach (FieldInfo field in fields)
{
// make sure we process only our variables
if (field.DeclaringType == currentType)
{
// see if the field is undoable or not
if (!NotUndoableField(field))
This check is present in CopyState() and UndoChanges(), but is missing from AcceptChanges().
(this errata does not affect the text or code shown in the book, but is a required change to the code download)
(Updated 4/8/2006)
View
|
p 520 (state discussion)
In the lower third of this page there's a Note with a reference to a URL with information about configuring session state in ASP.NET. The URL is misprinted. The text should read:
Note ASP.NET allows you to switch between three different state-handling models by simply changing the website’s web.config file (assuming you already have a SQL Server database server available in your environment). For an excellent overview of this feature, see “Understanding session state modes + FAQ” (http://forums.asp.net/7504/ShowPost.aspx).
(Updated 3/17/2006)
View
|
p 508 (ProjectEdit)
In the SaveProject() method in ProjectEdit, the resourcesBindingSource.DataSource property is set to null. This is incorrect, and the code should look like this:
this.resourcesBindingSource.DataSource = this.projectBindingSource;
(this text is in the middle of the code shown on the page)
(Updated 3/4/2006)
View
|
p 556 (ProjectEdit.aspx)
The SaveProject() method in ProjectEdit.aspx should catch the Csla.Validation.ValidationException and display details about the validation errors to the user. The SaveProject() method should look like this:
private int SaveProject(Project project)
{
int rowsAffected;
try
{
Session["currentObject"] = project.Save();
rowsAffected = 1;
}
catch (Csla.Validation.ValidationException ex)
{
System.Text.StringBuilder message = new System.Text.StringBuilder();
message.AppendFormat("{0}<br />", ex.Message);
if (project.BrokenRulesCollection.Count == 1)
message.AppendFormat("* {0}: {1}",
project.BrokenRulesCollection[0].Property,
project.BrokenRulesCollection[0].Description);
else
foreach (Csla.Validation.BrokenRule rule in project.BrokenRulesCollection)
message.AppendFormat("* {0}: {1}<br />", rule.Property, rule.Description);
this.ErrorLabel.Text = message.ToString();
rowsAffected = 0;
}
catch (Csla.DataPortalException ex)
{
this.ErrorLabel.Text = ex.BusinessException.Message;
rowsAffected = 0;
}
catch (Exception ex)
{
this.ErrorLabel.Text = ex.Message;
rowsAffected = 0;
}
return rowsAffected;
}
(this code replaces the first code shown on the page)
(Updated 3/4/2006)
View
|