Otra forma de acceder a los datos

Siempre he creído que trabajar con bases de datos es una de las tareas menos gratificantes que existen. El tener que leer datos una y otra vez, hacer la tarea rutinaria una y otra vez puede resultar denigrante. Claro, hay muchos que adoran esto, yo lo hago si no me queda más escapatoria. De cualquier manera, como la haraganería es la madre de la invención siempre que me toca hacer este trabajo trato de re pensar la forma de escribir código para que tenga que vérmelas lo menos posible con la base de datos y el manejo de los datos desde ella hacia el código. En fin, aquí les dejo otra forma, muy simple, de acceder a datos decorando las entidades de datos para que el llenado sea automático.

Primero una clase que servirá para decorar las entidades.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
internal sealed class ObjectDecorator
: Attribute
{
public ObjectDecorator(string databaseColumnName)
{
ColumnName = databaseColumnName;
}

public string ColumnName
{
get;
internal set;
}
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
internal sealed class InputParameterDecorator
: Attribute
{
public InputParameterDecorator(string inputParameter,
bool includeOnInsert)
{
InputParameter = inputParameter;
IncludeOnInsert = includeOnInsert;
}

public string InputParameter
{
get;
internal set;
}

public bool IncludeOnInsert { get; internal set; }
}

El segundo paso es tener alguna entidad decorada para almacenar información que viene desde la base de datos.

public class Product
{
[ObjectDecorator(“Id_Product”)]
[InputParameterDecorator(“productId”, false)]
public int ProductId { get; set; }

[ObjectDecorator(“Product_Name”)]
[InputParameterDecorator(“productName”, true)]
public string Name { get; set; }

[ObjectDecorator(“Product_Desc”)]
[InputParameterDecorator(“productDescription”, true)]
public string Description { get; set; }

[ObjectDecorator(“Product_Price”)]
[InputParameterDecorator(“productPrice”, true)]
public decimal Price { get; set; }

[ObjectDecorator(“Available”)]
[InputParameterDecorator(“productAvailable”, true)]
public bool Available { get; set; }
}

Finalmente la clase que se encargará de todos los procesos como la selección de datos, la inserción y la actualización.

internal class DataService<T>
where T : new()
{
public List<T> SelectMany(string query, params SqlParameter[] parameterCollection)
{
using (SqlConnection connection = new SqlConnection(ConfigurationHandling.getConnectionString))
{
SqlCommand command = new SqlCommand(query, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Clear();

if (parameterCollection.Length > 0)
command.Parameters.AddRange(parameterCollection);

connection.Open();

SqlDataReader reader = command.ExecuteReader();
List<T> returnList = CreateObjects(reader);

reader.Close();

return returnList;
}
}

public int Insert(string query, T updatableObject, params SqlParameter[] parameterCollection)
{
using (SqlConnection connection =
new SqlConnection(ConfigurationHandling.getConnectionString))
{
SqlCommand command = new SqlCommand(query, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Clear();

RecoverParameters(updatableObject, command, true);

if (parameterCollection != null
&& parameterCollection.Length > 0)
command.Parameters.AddRange(parameterCollection);

connection.Open();
int affectedRow = command.ExecuteNonQuery();
connection.Close();

return affectedRow;
}
}

public void Update(string query, T updatableObject , params SqlParameter[] parameterCollection)
{
using (SqlConnection connection =
new SqlConnection(ConfigurationHandling.getConnectionString))
{
SqlCommand command = new SqlCommand(query, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Clear();

RecoverParameters(updatableObject, command, false);

if (parameterCollection != null
&& parameterCollection.Length > 0)
command.Parameters.AddRange(parameterCollection);

connection.Open();
command.ExecuteNonQuery();

connection.Close();
}
}

private void RecoverParameters(T updatableObject, SqlCommand command, bool isInserting)
{
foreach (PropertyInfo property in updatableObject.GetType().GetProperties())
{
object[] propertyList =
property.GetCustomAttributes(typeof(InputParameterDecorator), true);

if (propertyList.Length > 0)
{
string parameterName = (propertyList[0] as InputParameterDecorator).InputParameter.ToString();
bool includeParameter = (propertyList[0] as InputParameterDecorator).IncludeOnInsert;

if (includeParameter || !isInserting)
{
command.Parameters.Add(new SqlParameter(parameterName,
property.GetValue(updatableObject, null)));
}
}
}
}

internal List<T> CreateObjects(IDataReader reader)
{
List<T> genericObject = new List<T>();

while (reader.Read())
{
T concreteObject = new T();
foreach (PropertyInfo property in concreteObject.GetType().GetProperties())
{
object[] propertyList = property.GetCustomAttributes(typeof(ObjectDecorator), true);

if (propertyList.Length > 0)
{
string attributeType = (propertyList[0] as ObjectDecorator).ColumnName.ToString();
property.SetValue(concreteObject, reader[attributeType], null);
}
}

genericObject.Add(concreteObject);
}

return genericObject;
}
}

Para llamar a cualquiera de las funciones podemos hacer lo siguiente.

public List<Product> AllProducts()
{
DataService<Product> dataService = new DataService<Product>();
return dataService.SelectMany(“GetAllProductList”);
}

Para los demás métodos.

public Product ProductById(int productId)
{
DataService<Product> dataService = new DataService<Product>();

Product producto = dataService.SelectMany(“GetProduct”,
new SqlParameter(“productId”, productId)).FirstOrDefault();

if (producto != null)
return producto;
else
{
throw new Exception(“Producto inexistente”);
}
}

O si no.

public void InsertNew(Product product)
{
DataService<Product> dataService = new DataService<Product>();
dataService.Insert(“InsertProduct”, product, null);
}

Definitivamente no es la mejor solución pero es una de tantas para hacer algo rápido.


2 comentarios on “Otra forma de acceder a los datos”

  1. […] January 2011 (2)December 2010 (5)November 2010 (4)October 2010 (11)September 2010 (1)June 2010 (2)April 2010 (2)March 2010 (1)February 2010 (2)January 2010 (2)December 2009 (2)November 2009 (2)October 2009 (6)September 2009 (1)December 2008 (1)May 2008 (1)December 2007 (2)November 2007 (1)July 2007 (1)December 2006 (1)October 2006 (1)January 2006 (1)August 2005 (1) Siempre he creído que trabajar con bases de datos es una de las tareas menos gratificantes que existen. El tener que leer datos una y otra vez, hacer la tarea rutinaria una y otra vez puede resultar denigrante. Claro, hay … Sigue leyendo → Read More… […]

  2. […] con el uso de atributos decorativos para las entidades. Podemos ver algo de código en el siguiente link. LikeBe the first to like this […]


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s