I'm trying to get this Generic DuplicateValidationRule working, which basically checks a Collection for duplicates (based on a generic business object type passed in). Lets take the IBankAccount Business Object for example:
public interface IBankAccount : IMyBusinessObjectBase
{
IBank Bank
{
get;
set;
}
IBankAccountType BankAccountType
{
get;
set;
}
string AccountName
{
get;
set;
}
string AccountNumber
{
get;
set;
}
DateTime EffectiveDate
{
get;
set;
}
}
Lets say I have the following collection of IBankAccount
IBankAccount acc1 = new BankAccount();
acc1.AccountName = "Account1";
acc1.AccountNumber = "123456";
acc1.Bank = FetchBusinessObjectByID(1); //Fetch Bank 1
IBankAccount acc2 = new BankAccount();
acc2.AccountName = "Account2";
acc2.AccountNumber = "654321";
acc2.Bank = FetchBusinessObjectByID(1); //Fetch Bank 1
IBankAccount acc3 = new BankAccount();
acc3.AccountName = "Account3";
acc3.AccountNumber = "123456";
acc3.Bank = FetchBusinessObjectByID(2); //Fetch Bank 2
IBankAccount acc4 = new BankAccount();
acc4.AccountName = "Account3";
acc4.AccountNumber = "123456";
acc4.Bank = FetchBusinessObjectByID(1); //Fetch Bank 2
ICollection<IBankAccount> bankAccounts = new List<IBankAccount>();
bankAccount.Add(acc1);
bankAccount.Add(acc2);
bankAccount.Add(acc2);
bankAccount.Add(acc4);
Parameters:
T = BusinessObject Type Class (Person,Address,BankAccount,Bank,BankBranch etc) string[] entityPropertyName = Array of properties to include when checking for duplicates.
Now lets use the following senario: Lets say I want to check for duplicate BankAccounts, by checking the on the account number, and the bank. The Account Number is unique within a bank, but can exist in another bank. So if you look at the list above, Acc1,Acc2 and Acc3 is valid. Acc4 is invalid because that account number for that Bank already exist.
So, the call to validate would look like this.
DuplicateValidationRule.Validate(newBankAccountEntry,new string[] {"AccountNumber","Bank.Name"});
The code above passes in the the business entity to check duplicates for, and the property array which includes the properties to check against.
public ValidationError Validate<T>(T entityProperty, string[] entityPropertyName)
{
ICollection<T> businessObjectList = FetchObjectsByType<T>();
bool res = true;
for (int i = 0; i < entityPropertyName.Length; i++)
{
object value = getPropertyValue(entityProperty, entityPropertyName[i]);
//By Using reflection and the getPropertyValue method I can substitute the properties to //compare.
if (businessObjectList.Any(x => getPropertyValue(x, entityPropertyName[i]).Equals(value) &&
x.GetType().GetProperty("ID").GetValue(x,null).ToString()
!= ((IBusinessObjectBase)entityProperty).ID.ToString()))
res &= true;
else
res &= false;
}
if (res)
return new ValidationError(_DuplicateMessage);
else
return ValidationError.Empty;
}
This method is used to get the actual object to check the duplicates on:
private static object getPropertyValue(object obj, string propertyName)
{
string[] PropertyNames = propertyName.Split('.');
object propertyValue = obj;
for (int i = 0; i < PropertyNames.Length; i++)
{
propertyValue = propertyValue.GetType().GetProperty(PropertyNames[i], BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy).
GetValue(propertyValue, null);
}
if (propertyValue.GetType() == typeof(string))
return propertyValue.ToString().ToLower(CultureInfo.CurrentCulture);
else
return propertyValue;
}
The above code works, but it has a flaw: The code above will only work if you check a single property for a duplicate match:
DuplicateValidationRule.Validate<IBankAccount>(newBankAccountEntry,new string[] {"AccountNumber"});
When you add another property to check against, for example:
DuplicateValidationRule.Validate<IBankAccount>(newBankAccountEntry,new string[] {"AccountNumber","Bank.Name"});
then the code will check the second property, on the next occurange in the list. It should test all the properties in the .Any for the currently object being compared. Hope this makes sence, maybe someone can give me some advice on how to fix this! Thanks :)