Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have following C# code. It helped me to avoid some code repetition in a good way.

The ExecuteQueryGenericApproach<T> method receives a Func generic delegate as argument. The delegated method has a parameter which receives IDataRecord as argument. That is, the ExecuteQueryGenericApproach<T> method provides the required IDataRecord to the functions passed to it.

QUESTIONS

  1. What is the name of this pattern? (Based on GoF design patterns)
  2. Is there any other scenario where this pattern is used?

Note: Knowing the name of this pattern will help me to better research on this and find opportunities to use it.

CommonDAL

public class CommonDAL
{
    public static IEnumerable<T> ExecuteQueryGenericApproach<T>(string commandText, List<SqlParameter> commandParameters, Func<IDataRecord, T> methodToExecute)
    {
        string connectionString = @"Server=XXXX;Database=AS400_Source;User Id=dxxx;Password=xxxx5";

        //Action, Func and Predicate are pre-defined Generic delegates.
        //So as delegate they can point to functions with specified signature.

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = connection;
                command.CommandType = CommandType.Text;
                command.CommandText = commandText;
                command.CommandTimeout = 0;

                if (commandParameters != null)
                {
                    command.Parameters.AddRange(commandParameters.ToArray());
                }

                connection.Open();
                using (var rdr = command.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        yield return methodToExecute(rdr);
                    }
                    rdr.Close();
                }
            }
        }
    }
}

EmployeeDAL

 public class EmployeeRepositoryDAL
    {
        public static List<Employee> GetEmployees()
        {
            string commandText = @"SELECT E.EmployeeID,E.EmployeeName,R.RoleID,R.RoleName FROM dbo.EmployeeRole ER
                                    INNER JOIN dbo.Employee E  ON E.EmployeeID= ER.EmployeeID
                                    INNER JOIN dbo.[Role] R ON R.RoleID= Er.RoleID ";

            //IEnumerable<Employee> employees = MyCommonDAL.ExecuteQueryGenericApproach<Employee>(commandText, commandParameters, Employee.EmployeeFactory);

            //Group By is needed for listing all the roles for an employee.
            IEnumerable<Employee> employees = CommonDAL.ExecuteQueryGenericApproach<Employee>(commandText, null, Employee.EmployeeCreator)
                                                    .GroupBy(x => new { x.EmployeeID, x.EmployeeName },
                                                            (key, group) =>
                                                                            new Employee
                                                                            {
                                                                                EmployeeID = key.EmployeeID,
                                                                                EmployeeName = key.EmployeeName,
                                                                                Roles = group.SelectMany(v => v.Roles).ToList()
                                                                            }
                                                            ).ToList();


            return employees.ToList();
        }


    }

Entity

public class Employee
{
    public int EmployeeID { get; set; }
    public string EmployeeName { get; set; }
    public List<Role> Roles { get; set; }

    //IDataRecord Provides access to the column values within each row for a DataReader
    //IDataRecord is implemented by .NET Framework data providers that access relational databases.

    //Static Method
    public static Employee EmployeeCreator(IDataRecord record)
    {
        var employee = new Employee
        {
            EmployeeID = (int)record[0],
            EmployeeName = (string)record[1],
            Roles = new List<Role>()
        };

        employee.Roles.Add(new Role { RoleID = (int)record[2], RoleName = (string)record[3] });
        return employee;

    }
}
share|improve this question
    
Could you maybe remove some of the implementation details so that your pattern becomes more obvious? I don't think that the problem domain (Employee modelling), SQL requests, or details of the implementation language are really relevant to demonstrate this pattern. –  amon Jan 21 at 13:50
2  
@amon I have provided a high level summary on the top portion of the post. I think it is good to have the complete code and it is not too lengthy. –  Lijo Jan 21 at 13:54
2  
The high level overview makes it sound like a higher-order functional implementation of the strategy pattern. You'll not find that specific case in many OO design pattern books because the object oriented types are only just realising that functional programming has a lot to teach them. –  Phoshi Jan 21 at 15:05
5  
I wouldn't say you've found a pattern, but you've created the bare workings of an ORM. –  Kevin Jan 21 at 15:19

1 Answer 1

I don't really think this is a design pattern. First reason is that GoF design patterns were are OOP with zero knowledge of first-class functions or generics. Both which are used in your example.

One important thing to remember: Not everything is a design pattern. Just because something saved you some time doesn't make it a design pattern. If you follow a proper design principles, you can create a good, extensible code without even knowing a single design pattern. Design patterns are only good if you want to communicate what the code does to someone else.

share|improve this answer
    
The word "communicate" is the key point. If we can figure out what is the name I can easily communicate with other team members. Generics and Delegates are easier ways of implementing design patterns in C#. –  Lijo Jan 21 at 14:57
    
@Lijo If you want to name it, then do it. But make sure you have solid definition what falls under that name and what does not. And I disagree about generics and delegates. They actually make OOP design patterns much harder to understand. –  Euphoric Jan 21 at 15:01
2  
Just because something wasn't in the GoF book doesn't mean it isn't a design pattern. If you find that you're repeating a particular pattern when you design your code, guess what? It's a design pattern. –  Ant Feb 20 at 15:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.