Execute Set of ValidationRule-C# Class Design - Better Approach
Asked Answered
S

2

13

I have a case there I need to execute set of validation rules for different companies. There will be multiple validation rules against one Company.

So I have following table Structure

Company

ID      CompanyName  
1       ABC   
2       DEF  

ValidationRule

RuleID      Name  
1           Rule1   
2           Rule2 

CompanyValidationRuleMapping

MappingID      CompanyId    RuleID
1              1             1
2              1             2
3              2             2

I have separate stored procedures for every validation rule.

So from my c# code, I will find all validation rule corresponding to a company and need to execute the validation stored procedure associated with that rule.

So I am planning to keep one Interface 'IValidation' which is having different validation methods.

Or

Can i have to create different classes for each validation which implements an interface

Can anyone please suggest a better approach on this.

Strephonn answered 7/2, 2017 at 9:1 Comment(6)
Forgive my ignorance but what exactly is an SP?Emmaline
@CKing Stored ProcedureMice
So for each rule you must execute a stored procedure?Hooves
@ATC..Yes..After validation i need to raise different service calls.My doubts is with class designStrephonn
I do not know how your software is designed, or if I understand correctly. Are you validating already saved entires in the database? Validation in my opinion best placed 1, after user input, before calling any business logic; 2, after business logic has run and before saving to the database. So to validate the business objects or entities.Prine
@jannagy02 ..I am validating already saved entires in the databaseStrephonn
M
1

Your first level of generic validation interface which gives the flexibility of providing both result type and the model to be validated:

public interface IValidate<T, R>
    where T : class
    where R : class // where T is any custom result and R is your custom model
{
    T Validate(R model);
}

Let's say, I need to validate company policies which would be handled by a different sp altogether:

public interface IValidateCompanyPolicies : IValidate<ValidationResult1, Company>
{
  ValidationResult1 Validate(Company model);
}

Again, I also need to check for company monetary accounts, taxes, audits etc:

public interface IValidateCompanyAccounts : IValidate<ValidationResult2, Company>
{
  ValidationResult2 Validate(Company model);
  bool HasAuditPassed(Company model);
}

Resp. classes handling both kinds of IValidate interface

public class ValidateCompanyPolicies : IValidateCompanyPolicies
{
    ValidationResult1 Validate(Company model)
    {
        // Hit stored procedure corresponding to company policies validation
    }
}

public class ValidateCompanyAccounts : IValidateCompanyAccounts
{
    ValidationResult2 Validate(Company model)
    {
        // Hit stored procedure corresponding to company's monetary accounts validation
    }

    bool HasAuditPassed(Company model)
    {
        // Hit stored procedure corresponding to get company audit results
    }
}

My end class which needs to perform all business intensive operations after performing validation:

public class XYZCompany
{
    private IValidateCompanyPolicies companyPoliciesValidation;

    private IValidateCompanyAccounts companyAccountsValidation;

    public XYZCompany(
        IValidateCompanyPolicies companyPoliciesValidation,
        IValidateCompanyAccounts companyAccountsValidation)
    {
        // Perform DI
    }

    public bool UpdateCompany(Company model)
    {
        var checkPolicies = this.companyPoliciesValidation.Validate(model);

        if (checkPolicies.Success)
        {
            var checkAccounts = this.companyAccountsValidation.Validate(model);

            var auditSuccess = this.companyAccountsValidation.HasAuditPassed(model);

            if (checkAccounts.Success && auditSuccess)
            {
                // Perform DB save
            }
        }
    }
}
Maltha answered 14/2, 2017 at 15:29 Comment(1)
@RRM..Thank u so much for ur detailed answer.. i will try thisStrephonn
P
0

There is a couple of scenarios:

  • If all the Valudation SP have the same parameters and results, you can create a single class to call the all SPs and just store the SP names in the CompanyValidationRuleMapping table. See Called SP from another SP

  • If every SP is very different, then you would need a different class for each SP

I would recommend creating all SP with the same parameters and result, since this approach would be easier to expand and change.

Pitchy answered 12/2, 2017 at 22:40 Comment(3)
Parameters will be same .But it returns different resultsStrephonn
Separate class for each rule implementing IValidation will be better, how the validation is run can change(for now you are using SP, this itself may change) and the caller of IValidation class simply bother with what the underlying method of IValidation returns, which itself will contain all the detail regarding the result of Validation.Grass
Just be mindful of the the company resources,not long ago I worked a place that used many rules and where most of the guys that did a lot of maintenance were really good at SQL and not C#, so in that case having more SP than C# classes would be better.Pitchy

© 2022 - 2024 — McMap. All rights reserved.