I came across this bug last night,
which was occurring right as CSLA 4
was released. It had to deal with the
CodeSmith CSLA templates
when you set UseMemberVariables
to true
. The error is quite obscure and not
very intuitive as the signs of a bug are only found when you check to see if
your business object IsValid. The scenario in this case is when you set a
required managed property, the rules never fully evaluate the set value. A
bunch of other side effects could occur as well. Here is the error you could
receive:
CategoryId required
Expected:True
But was:False
Here is the code that was causing the error:
CSharp
protected override void AddBusinessRules()
{
BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(_categoryIdProperty));
}
private static readonly PropertyInfo<System.String> _categoryIdProperty = RegisterProperty<System.String>(p => p.CategoryId, String.Empty);
private System.String _categoryId = _categoryIdProperty.DefaultValue;
public System.String CategoryId
{
get { return GetProperty(_categoryIdProperty, _categoryId); }
set { SetProperty(_categoryIdProperty, ref _categoryId, value); }
}
[Test]
private void CreateCategory(string categoryID)
{
Category category = Category.NewCategory();
category.CategoryId = categoryID;
Assert.IsTrue(category.IsValid, category.BrokenRulesCollection.ToString());
category = category.Save();
Assert.IsTrue(category.CategoryId == categoryID);
}
Visual Basic
Protected Overrides Sub AddBusinessRules()
BusinessRules.AddRule(New Csla.Rules.CommonRules.Required(_categoryIdProperty))
End Sub
Private Shared ReadOnly _categoryIdProperty As PropertyInfo(Of System.String) = RegisterProperty(Of System.String)(Function(p As Category) p.CategoryId, String.Empty)
Private _categoryId As System.String = _categoryIdProperty.DefaultValue
Public Property CategoryId() As System.String
Get
Return GetProperty(_categoryIdProperty, _categoryId)
End Get
Set (value As System.String)
SetProperty(_categoryIdProperty, _categoryId, value)
End Set
End Property
<test()> _
Private Sub CreateCategory(ByVal categoryID As String)
Dim category As Category = PetShop.Tests.ParameterizedSQL.Category.NewCategory()
category.CategoryId = categoryID
Assert.IsTrue(category.IsValid, category.BrokenRulesCollection.ToString())
category = category.Save()
Assert.IsTrue(category.CategoryId = categoryID)
End Sub
As you can see the code looks and works fine in CSLA 3.8 but it isn’t the case
in 4.0. Once I tracked down what was causing the error, I saw that there wasn’t
any checks in CSLA4 to see if the property had the RelationshipTypes.PrivateField
overload when you are calling the GetProperty
or SetProperty
methods with a
backing field. The long term fix when using private member backing fields is to
set the RelationshipTypes
to RelationshipTypes.PrivateField
.
CSharp
private static readonly PropertyInfo<System.String> _categoryIdProperty = RegisterProperty<System.String>(p => p.CategoryId, String.Empty, RelationshipTypes.PrivateField);
private System.String _categoryId = _categoryIdProperty.DefaultValue;
public System.String CategoryId
{
get { return GetProperty(_categoryIdProperty, _categoryId); }
set { SetProperty(_categoryIdProperty, ref _categoryId, value); }
}
Visual Basic
Private Shared ReadOnly _categoryIdProperty As PropertyInfo(Of System.String) = RegisterProperty(Of System.String)(Function(p As Category) p.CategoryId, String.Empty, RelationshipTypes.PrivateField)
Private _categoryId As System.String = _categoryIdProperty.DefaultValue
Public Property CategoryId() As System.String
Get
Return GetProperty(_categoryIdProperty, _categoryId)
End Get
Set (value As System.String)
SetProperty(_categoryIdProperty, _categoryId, value)
End Set
End Property
This has been fixed in a nightly build of the CodeSmith CSLA Templates and will be in version 3.0.1 of the CodeSmith CSLA Templates. The CSLA team will also be releasing version 4.0.1 of CSLA sometime soon. If you don’t have this overload set in CSLA 4.0.1 then you will receive the following exception:
Properties with private backing fields must be marked as RelationshipTypes.PrivateField
If you are using the CodeSmith CSLA templates, remember to update to the latest templates and regenerate. If you are not, well you should be using the CodeSmith CSLA Templates as it is about to save you a ton of time adding the RelationshipTypes.PrivateField overload to all of your properties!
Share this post
Twitter
Facebook
Reddit
LinkedIn
Email