1

I am trying to create a generic method that will take a Func parameter.

traditional func is that we create methodOne() and send it as a parameter to another method. However, that will defeat the purpose of making the method I am trying to create as a generic.

My code:

public static List<T> ExecuteQuery<T>(string connection, 
                                      string commandText, 
                                      Func<SqlDataReader, List<T>> myMethodName)
{
    List<T> items = new List<T>();
    SqlDataReader sqlDataReader = null;

    try
    {
        using (SqlConnection con = new SqlConnection(connection))
        {
            using (SqlCommand cmd = new SqlCommand(commandText, con))
            {
                try
                {
                    con.Open();
                    sqlDataReader = cmd.ExecuteReader();

                    items = myMethodName(sqlDataReader);
                }
                catch (Exception ex)
                {
                    if (sqlDataReader != null) sqlDataReader.Close();

                    cmd.Dispose();

                    throw ex;
                }
                finally
                {
                    if (sqlDataReader != null) sqlDataReader.Dispose();

                    cmd.Dispose();
                }
            }
        }
    }
    catch (Exception)
    {
        throw;
    }

    return items;
}

Trying to call the method above like this:

    public List<Function> GetDeletedFunctions(string connectionString)
    {
        SqlDataReader sqlDataReader = null;
        List<Function> functions;

        string cmdText = @"SELECT * FROM Table "; // dumy query

        functions = DbHelper.ExecuteQuery<Function>(
          connectionString, 
          cmdText, 
          List<Function>(sqlDataReader)
        {

            var f =
            (from x in sqlDataReader.Cast<DbDataRecord>()
             select new Function
             {
                 Param1 = DbHelper.GetValue<string>("Param1 ", x),
                 Param2 = DbHelper.GetValue<string>("Param2", x),
             }).ToList();

            return f;
        } );
}

Compile Time Error:

Error CS1955 Non-invocable member 'List' cannot be used like a method.

I am assuming there is a syntax issue here and its driving me nuts. Any suggestions?

1
  • First off you don´t assign anything to your sqlDataReader. Commented Mar 15, 2019 at 9:45

2 Answers 2

2

When wrapping into using you don't have to catch exceptions (.Net will free resources for you, rain on shine)

// Dangerous practice: what if I put commandText "drop table MyTable"?
public static List<T> ExecuteQuery<T>(string connection, 
                                      string commandText, 
                                      Func<SqlDataReader, List<T>> myMethodName) {
  //ToDo: Validate parameters here

  using (var con = new SqlConnection(connection)) {
    con.Open();

    using (var cmd = new SqlCommand(commandText, con)) {
      // IDataReader is IDisposable as well       
      using (var reader = cmd.ExecuteReader()) {
        return myMethodName(reader);
      } 
    }
  }  
}

Then all we have to do is to provide arguments: connectionString, commandText and map function; let's do it:

public List<Function> GetDeletedFunctions(string connectionString) {
  //TODO: Validate connectionString here 

  return DbHelper.ExecuteQuery<Function>(
     connectionString,                                // Connection String
   @"SELECT * FROM Table ",                           // Query
    (reader) => {                                     // Map function
       // When given reader, the map function creates list
       List<Function> result = new List<Function>();

       // Convert each record into Function instance and add them into the list
       while (reader.Read()) {
         Function item = new Function() {
           Param1 = Convert.ToString(reader["Param1"]),
           Param2 = Convert.ToString(reader["Param2"]),
         }

         result.Add(item); 
       }

       // and return the list
       return result;
    }
  )
}
Sign up to request clarification or add additional context in comments.

6 Comments

Excellent answer! Thank you, If I could just bother you with one thing: " (reader) => " this syntax is the equivalent of? and also the "reader" does not exist as a parameter anywhere in the code but I am not getting any errors, how come?
reader is a parameter being passed to a function written after => (Lambda Expression)
(reader) => {body} is typical syntax of a lambda function where reader is formal parameter (you can change it into, say, r)
Again thank you! tend to use lambada expressions when doing the linq queries but never done it as a function like this.
@ThunD3eR: delegate is a typical alternative to lambda function. learn.microsoft.com/en-us/dotnet/api/…
|
1

There is problem in the way you are trying to pass function as parameter. Please use the following code:

public List<Function> GetDeletedFunctions(string connectionString)
{                        
    string cmdText = @"SELECT * FROM Table "; // dumy query
    return DbHelper.ExecuteQuery<Function>(connectionString,
                                           cmdText,
                                           (SqlDataReader sqlDataReader) =>
                                           {
                                               var f = (from x in sqlDataReader.Cast<DbDataRecord>()
                                               select new Function
                                               {
                                                   Param1 = DbHelper.GetValue<string>("Param1 ", x),
                                                   Param2 = DbHelper.GetValue<string>("Param2", x)
                                               }).ToList();

                                               return f;
                                           });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.