HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

IEnumerable extension method that ingests SqlCommand and returns query results

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
methodsqlcommandqueryingestsextensionthatreturnsandresultsienumerable

Problem

The following ingests a preexisting SqlCommand and returns the values.

A couple caveats right now.

1 ) Type properties must be named identical to the SQL column

2) properties must be given a custom [SQLColumn] attribute.

The attribute contains a string which I plan to use later for variation in property names while keeping column designation.

public static IEnumerable FromCommand(this IEnumerable b, SqlCommand command)
    {

        using (command.Connection)
        {

            command.Connection.Open();

            using (var reader = command.ExecuteReader())
            {

                var readerColumns = new HashSet(Enumerable.Range(0, reader.FieldCount).Select(reader.GetName));
                var properties = typeof(T).GetProperties().Where(o => o.IsDefined(typeof(SQLColumn)) && readerColumns.Contains(o.Name)).ToList();

                while (reader.Read())
                {

                    object OUTPUT = Activator.CreateInstance(typeof(T));

                    foreach (var item in properties)
                    {
                        item.SetValue(OUTPUT, reader[item.Name] is DBNull ? null : reader[item.Name]);
                    }

                    yield return (T)Convert.ChangeType(OUTPUT, typeof(T));
                }
            }
        }
    }


As requested, here is an example of the class utilizing the extension method.

```
public class MyType
{

#region Properties Block

[SQLColumn]
public Guid GuidColumn { get; set; }

[SQLColumn]
public int IntColumn { get; set; }

[SQLColumn]
public bool BitColumn { get; set; }

#endregion Properties Block

#region Select Block

[Description("Selects and returns all rows.")]
public static IEnumerable SelectAll()
{

SqlCommand command = new SqlCommand(QueryRepository.SELECT_MyType_ALL, Conn.ConnectionString) { CommandTimeout = 0 };

return new List().FromCommand(command);

}

[Description("Selects an

Solution

You are never using b in the method. Why make it an extension method if you are going to completely ignore the first argument? In order to use this code, you need to create a new instance that is immediately thrown away. That is unneeded waste.

Instead, you can just specify the generic type in the function call.

public static IEnumerable FromCommand(SqlCommand command)
{
    // ...
}

[Description("Selects and returns all rows.")]
public static IEnumerable SelectAll()
{
    SqlCommand command = new SqlCommand(QueryRepository.SELECT_MyType_ALL, Conn.ConnectionString) { CommandTimeout = 0 };

    return FromCommand(command);
}


The expression that assigns to properties is over 100 characters. That doesn't count the indentation or the variable declaration. That is going to be hard to follow. I suggest that you extract the lambda being passed to Where() into a static function with a descriptive name. That way I don't need to think about what is being filtered out.

You are adding extra blank lines after opening curly brackets and before some closing curly brackets. This is just inflating the file size and not helping readability.

Code Snippets

public static IEnumerable<T> FromCommand<T>(SqlCommand command)
{
    // ...
}

[Description("Selects and returns all rows.")]
public static IEnumerable<MyType> SelectAll()
{
    SqlCommand command = new SqlCommand(QueryRepository.SELECT_MyType_ALL, Conn.ConnectionString) { CommandTimeout = 0 };

    return FromCommand<MyType>(command);
}

Context

StackExchange Code Review Q#107554, answer score: 2

Revisions (0)

No revisions yet.