Per-Object Rules
I need a business rule in my object where I must check against the database for duplicates, but this is determined by two properties so I need to have the object to get both values from the object when my SP is executed.
In my object I have created the class for my rule
public class ShareTypeRule : Csla.Rules.BusinessRule
{
protected override void Execute(RuleContext context)
{
ShareType target = (ShareType)context.Target;
bool stypeExist = true;
stypeExist = target.getSedolExist(target.Sedol, target.Company_Id);
if (stypeExist)
{
AffectedProperties.Add(SedolProperty);
context.AddErrorResult(SedolProperty, "Share Type already exist for selected company");
}
}
}
In my server side I created a function (getSedolExist)(This function makes the database call) on my object that returns the Boolean value.
I also added a trigger to my user control on the LostFocus event it calls a method in my viewmodel, which then calls the Checkrules() method.
Problem is that when I build it needs the function getSedolExist in my client side code and when the Checkrules()
You need to use a command object in your rule, not a direct server method call.
Within your business layer the ONLY code that can interact with server-side methods, assemblies, or features is the code in DataPortal_XYZ methods.
ABSOLUTELY NO OTHER CODE CAN USE SERVER-SIDE FEATURES.
The ProjectTracker app implements an Exists command as an example of what you need to do. And I specifically discuss this in the Using CSLA 4 ebook series.
Hi,
You can also look at the Samples\Net\cs\RuleTutorial sample - and specifically the LookupRole and AsyncLookupRule.
You must use a CommandObject (or ReadOnlyObject) to do the database lookup.
thx for the info.
I have added the code to use a commandbase object in my rule.
public class ShareTypeRule : Csla.Rules.BusinessRule
{
protected override void Execute(RuleContext context)
{
ShareType target = (ShareType)context.Target;
if (!string.IsNullOrEmpty(target.Sedol))
{
var cmd = new ShareTypeExistCommand(target.Sedol, target.Company_Id);
DataPortal.BeginExecute<ShareTypeExistCommand>(cmd, (o, e) =>
{
if (e.Object != null)
{
if (e.Error != null)
throw e.Error;
else
if (e.Object.ShareTypeExists == true)
{
AffectedProperties.Add(SedolProperty);
context.AddErrorResult(SedolProperty, "Share Type already exist for selected company");
target.PropertyHasChanged(SedolProperty);
}
}
});
}
}
}
The way I have called the Checkrules was to add a trigger action to my lost focus event on the textbox of my usercontrol and added the following code to the method called by the trigger action in my viewModel
if (Model != null)
Model.CheckRules();
This in turn calls the CheckRules() method created in my client side code.
public void CheckRules()
{
BusinessRules.CheckRules();
OnPropertyChanged("Sedol");
}
The problem now lies with the asynch call to the DB to check if the code entered already exists. The OnPropertyChanged on my client side code gets excecuted before the call to the database is completed and therefore the errorResult does not get reported back to the used.
Property rules is automatically triggered when a property is set in the UI. You should not need to call CheckRules in the view model for each edit of fields.
I highly recommend the Using Csla 4 ebooks from Rocky. !!!
Thx...I see chapter 2 creating Business objects using CSLA 4 explains the rule system in detail and I managed to get it working.
Copyright (c) Marimer LLC