Improve data access layer select method Pattern

后端 未结 7 906
眼角桃花
眼角桃花 2020-12-05 05:46

Lately I find myself writing data access layer select methods where the code all takes this general form:

public static DataTable GetSomeData( ... arguments)         


        
相关标签:
7条回答
  • 2020-12-05 06:43

    Similar to what I posted here

    public IEnumerable<S> Get<S>(string query, Action<IDbCommand> parameterizer, 
                                 Func<IDataRecord, S> selector)
    {
        using (var conn = new T()) //your connection object
        {
            using (var cmd = conn.CreateCommand())
            {
                if (parameterizer != null)
                    parameterizer(cmd);
                cmd.CommandText = query;
                cmd.Connection.ConnectionString = _connectionString;
                cmd.Connection.Open();
                using (var r = cmd.ExecuteReader())
                    while (r.Read())
                        yield return selector(r);
            }
        }
    }
    

    I have these simple extension methods to aid ease of calling:

    public static void Parameterize(this IDbCommand command, string name, object value)
    {
        var parameter = command.CreateParameter();
        parameter.ParameterName = name;
        parameter.Value = value;
        command.Parameters.Add(parameter);
    }
    
    public static T To<T>(this IDataRecord dr, int index, T defaultValue = default(T),
                          Func<object, T> converter = null)
    {
        return dr[index].To<T>(defaultValue, converter);
    }
    
    static T To<T>(this object obj, T defaultValue, Func<object, T> converter)
    {
        if (obj.IsNull())
            return defaultValue;
    
        return converter == null ? (T)obj : converter(obj);
    }
    
    public static bool IsNull<T>(this T obj) where T : class
    {
        return (object)obj == null || obj == DBNull.Value;
    }
    

    So now I can call:

    var query = Get(sql, cmd =>
    {
        cmd.Parameterize("saved", 1);
        cmd.Parameterize("name", "abel");
    }, r => new User(r.To<int>(0), r.To<string>(1), r.To<DateTime?>(2), r.To<bool>(3)));
    foreach (var user in query)
    {
    
    }
    

    This is fully generic, fits any model that comply to ado.net interfaces. The connection object and reader is disposed only after the collection is enumerated once.

    0 讨论(0)
提交回复
热议问题