views:

350

answers:

1

Hi

I'm creating a C# application using ActiveRecord as my datalayer. I've created a business class named UserGrabber which is supposed to find users by using it's properties to send as filters into a ActiveRecord.Find Method.

For example a User class. The client needs to find all users that have active directory name starting with "anna" and with SSN containing 4229. Then I would like to do

UserGrabber grabber = new UserGrabber();
grabber.ADName = "anna";
grabber.SSN = "4229";
grabber.Grab();

foreach(User user in grabber.Users)
{
    Console.WriteLine(user.FullName);
}

The trick is that I don't have to send information to UserGrabber unless I want to filter by it, I could have send just in grabber.ADName, then the SSN would not be filtered by.

The problem is I can't seem to grasp how to do this in ActiveRecord. Maybe I could use the ExecuteQuery(Castle.ActiveRecord.IActiveRecordQuery) or FindAll(NHibernate.Criterion.ICriterion) ?

A: 

Alright, I have figured this out :)

I started by creating class named ActiveRecordCustomBase with the following implementation

public class ActiveRecordCustomBase<T> : ActiveRecordBase<T>
    {
        public static string GetPropertyColumnName(string propertyName)
        {
            System.Reflection.PropertyInfo property = typeof(T).GetProperty(propertyName);
            object[] attributes = property.GetCustomAttributes(false);

            if (attributes != null)
            {
                foreach (object attr in attributes)
                {
                    if (attr is PrimaryKeyAttribute)
                    {
                        return ((PrimaryKeyAttribute)attr).Column;
                    }
                    else if (attr is PropertyAttribute)
                    {
                        return ((PropertyAttribute)attr).Column;
                    }
                }
            }
            return null;
        }
    }

By letting all my ActiveRecord classes inherit from ActiveRecordCustomBase, it allows me to use the function GetPropertyColumnName so that the column mapping will be in 1 location (therefore not vialoting the DRY principal).

Next I created a finder method in my business class which looks like this:

UserCriteria userCriteria = (UserCriteria)criteria;
                if (userCriteria.UserId != 0)
                {
                    UserDAO userDAO = UserDAO.TryFind(userCriteria.UserId);
                }
                else if (userCriteria.MasterDataId != 0)
                {
                    UserDAO userDAO = UserDAO.FindOne(Restrictions.Eq(UserDAO.GetPropertyColumnName("ExternalId1"), userCriteria.MasterDataId));

                }
                else if (!userCriteria.ADName.Equals(string.Empty))
                {
                    UserDAO userDAO = UserDAO.FindOne(Restrictions.Eq(UserDAO.GetPropertyColumnName("ADName"), userCriteria.ADName.ToLower()));
                }

That was enough to get the dynamic behaviour I was seeking

armannvg