jueves, 29 de enero de 2015

Ordenamiento de columnas en un GridView




Ordenamiento de columnas en un GridView  en Visual Studio .NET

Cuando usamos listas de entidades para ser mostradas en un GridView, éstas no permiten utilizar la opción de ordenamiento automático de columnas AllowSorting=true del GridView porque generan el siguiente error: “El origen de datos 'odsPersonaList' no admite la ordenación con datos IEnumerable. Sólo se admite la ordenación automática con DataView, DataTable y DataSet”.

Durante algún tiempo, intenté utilizar los métodos de ordenamiento de listas en la capa de presentación usando métodos del GridView, sin resultados.

Evitando ampliar la funcionalidad de las listas, opté por usar otro componente que integrara  la ordenación;  para lo cual fue suficiente buscar en internet un método que convirtiera la lista en un DataTable. En el ejemplo publicado a continuación podrán encontrar el código  que permita hacer esto. No sé de quién es originalmente, lo encontré en muchos sitios web, por ello espero que la persona que lo creó, me disculpe al no poder darle el crédito que se merece.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;

/// <summary>
/// Utilidades para aplicar a la capa de entidades de negocio del proyecto
/// </summary>

public class UtilidadesLN
{
                  public UtilidadesLN(){}
    public DataTable ConvertToDataTable<T>(IList<T> data)
    {
        PropertyDescriptorCollection properties =
           TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            table.Rows.Add(row);
        }
        return table;
    }
}

Mediante la funcionalidad anterior convierto una lista en un DataTable para ser expuesta como un objeto de datos en la capa de entidades de negocio.

public class PersonaLN:UtilidadesLN
{
    PersonaAD AD = new PersonaAD();
                  public PersonaLN()     {}

    //Consulta Normal usando una lista generica
    [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
    public List<PersonaEN> ConsultarPersona(String Buscar)
    {
        return AD.ConsultarPersonas(Buscar);
    }
    [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
    public DataTable ConsultarPersonaDT(String Buscar)
    {
        return ConvertToDataTable(AD.ConsultarPersonas(Buscar));
    }


}

Ilustración 1
De esta manera puedo utilizar ObjectDataSource en la capa de presentación, para acceder a los datos y poder utilizarlos desde un GridView. En la ilustración 1, podrán ver dos GridView enlazados, el primero con una lista y el segundo a un DataTable.

















El primer GridView enlazado a una Lista, en el momento de pulsar clic sobre el nombre de la columna va a generar el  error 'odsPersonaList' no admite la ordenación con datos IEnumerable. Sólo se admite la ordenación automática con DataView, DataTable y DataSet” (Ver ilustración 2):


Ilustración 2
Mientras que al usar un objeto conectado al método que devuelve un DataTable, el sistema ordenará las columnas de manera automática. A continuación se ve en la ilustración 3, el GridView al consultar los datos:

Ilustración 3
 Después de pulsar clic sobre la columna del nombre, el GridView ordena los datos sin generar error. a continuación en la ilustración 4, se pueden apreciar los datos ordenados descendentemente :

Ilustración 4
Este ejemplo lo realicé con Visual Studio Community  2013,  lenguaje C# y  clases en la carpeta App_code que emulan las capas del proyecto. Lo pueden descargar aquí. El código se entrega tal como está, o sea bajo su propia responsabilidad de uso.

Por favor, no olvides darle un “me gusta” al articulo si este ejemplo te es de utilidad. 

lunes, 5 de enero de 2015

Usando reflection, un ejemplo practico con C Sharp "C#"



Reflection es una herramienta sencilla en su concepto, pero un poco difícil en su manejo. Permite el acceso a objetos (ensamblados, módulos, propiedades, tipos de datos, etc) de manera dinámica.
Para poder comprender un poco más del tema, voy a mostrar el siguiente ejemplo:

Tengo una cantidad “n” de clases que necesito mostrar en formularios web, para evitar escribir por cada atributo de cada clase la sentencia de asignación de la propiedad al control web “txtUsuario.text = objeto.usuario”. Cree una clase con un método en la carpeta App_code de nombre “ManejoControles”, a esta clase le paso como parámetros el objeto y un panel que contiene los controles. Esta clase se encarga de recorrer los controles contenidos en el panel, en caso de ser  alguno de tres predeterminados (Texto, DropDownList y RadioButtonList), se busca por el nombre del control en el objeto el valor y se le asigna al control. (Espero haberme hecho entender).

Como estándar a cada control le asigno una nomenclatura en su nombre, las tres primeras letras corresponden al tipo de control y el resto del nombre corresponde al nombre de la propiedad del objeto. Adicionalmente dejo todos los controles que quiero llenar con los valores del atributo de un objeto dentro de un control panel de asp.net.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Logica;
using Entidades;
using System.Reflection;

        public void ObjetoPanel(Panel Panel, object Objeto)
        {
            String TipoControl;
            String Nombre = String.Empty;

            foreach (Control oControl in Panel.Controls)
            {
                TipoControl = oControl.GetType().ToString();
                switch (TipoControl)
                {
                    case "System.Web.UI.WebControls.TextBox":
                        TextBox oTextBox = (TextBox)oControl;
                        Nombre = oTextBox.ID.Substring(3, oTextBox.ID.Length - 3);
                        oTextBox.Text = Convert.ToString(Objeto.GetType().GetProperty(Nombre).GetValue(Objeto, null));
                        break;
                    case "System.Web.UI.WebControls.DropDownList":
                        DropDownList oLista = (DropDownList)oControl;
                        Nombre = oLista.ID.Substring(3, oLista.ID.Length - 3);
                        oLista.SelectedValue = Convert.ToString(Objeto.GetType().GetProperty(Nombre).GetValue(Objeto, null));
                        break;
                    case "System.Web.UI.WebControls.RadioButtonList":
                        RadioButtonList oRadio = (RadioButtonList)oControl;
                        Nombre = oRadio.ID.Substring(3, oRadio.ID.Length - 3);
                        oRadio.SelectedValue = Convert.ToString(Objeto.GetType().GetProperty(Nombre).GetValue(Objeto, null));
                        break;
                }

            }

        }

Si este ejemplo les es de utilidad, por favor no olvidar dejar un comentario o like.

Para el ejemplo use Web developer express 2013 que se consigue aquí.

jueves, 1 de enero de 2015

SQL server error 102 incorrect syntax near ' '

SQL server error 102 incorrect syntax near ' '

Este es uno de esos errores curiosos, lo vi hace poco cuando intente ejecutar un procedimiento almacenado en el servidor de producción, sin embargo cuando ejecutaba el procedimiento almacenado en mi maquina local, el error no aparecía, después de recordar códigos ASCII, encontré el problema.

Creo que en algún momento alguno de “Notostros”, los desarrolladores copiamos algún ejemplo o código de internet y junto con el ejemplo se ingresó en el procedimiento almacenado un espacio duro en vez de un espacio normal.

Para localizar el error utilice Word la opción de mostrar todo, que muestra los retornos de carro (Tecla enter) y los espacios los muestra como una especie de  punto localizado a la mitad de la altura de las letras “.” Y los espacios duros como un símbolo de grados “°”.

Para solucionar el error basta con copiar el “espacio duro”, llevarlo a la opción de buscar y reemplazar del Word (Ctrl + L: en español) y remplazarlo por un espacio normal.




Visual Studio 2013 No muestra las clases de la carpeta App_Code

Visual Studio 2013 No muestra las clases de la carpeta App_Code.

Hace poco decidí comenzar a hacer mis nuevos desarrollos con Visual Studio 2013, así que al crear mi primer aplicativo web comencé a utilizar algunas utilidades para manejo de controles y me encontré que en el nuevo Visual Studio 2013 para web cuando creas una clase dentro de la carpeta App_Code, a diferencia de con Visual Studio 2010, este no las compila de manera predeterminada, para esto tienes que entrar a las propiedades de la clase mediante clic derecho sobre el nombre de la clase y cambiar la opción de  “Acción de compilación” a compilación.

Con lo anterior podrás invocar las clases realizadas en tu carpeta App_code dentro de tus páginas web.




 Para descargar Visual Studio Web Developer express 2013, lo puedes bajar del siguiente enlace: Visual Studio 2013

lunes, 10 de noviembre de 2014

Optimización de Índices – Desfragmentación


Los índices en una base de datos con el tiempo tienden a fragmentarse, esto contribuye a disminuir el rendimiento de la base de datos. En SQL server tiene una opción para conocer la fragmentación de los índices de la base de datos
A continuación muestro una consulta  que lista las tablas del sistema, la cantidad de registros por tabla, sus índices y porcentaje de fragmentación. La consulta se ordena por orden de registros descendente.
--Consulta para extraer tablas y registros
Select Tablas.Tabla
       ,Tablas.Registros
       ,Indices.Indice
       ,Indices.Fragmentacion
       ,Round((Registros / 1000000),2) * 100 As Orden
From
(select Distinct SCS.name + '.' + SO.Name as Tabla
      ,si.rows as 'Registros'
from sysobjects as SO
    inner join sysindexes as SI on SO.Id = SI.id
    inner join sysfilegroups as SFG on SI.GroupId = SFG.GroupId
    inner join sys.objects SOS On SO.id=SOS.object_id
    inner join sys.schemas SCS On SOS.schema_id = SCS.schema_id) As Tablas
    Inner Join (SELECT d.name + '.' + c.name as Tabla
                      ,b.name As Indice
                      ,a.avg_fragmentation_in_percent 'Fragmentacion'
                FROM sys.dm_db_index_physical_stats (DB_ID(N'Cuentame'), NULL, NULL, NULL, NULL) AS a
                     JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id
                     Join sys.objects AS c on b.object_id = C.object_id
                     Join sys.schemas AS d ON c.schema_id = d.schema_id
WHERE b.name is Not NUll) As indices
      On Tablas.Tabla=indices.Tabla
Order By Registros Desc

Una vez ejecutado el listado, puedes seleccionar la tabla e índice que veas más fragmentado y reorganizar o reconstruir mediante la siguiente sentencia.
ALTER INDEX [NombreIndice] on [Esquema].[Tabla] REORGANIZE
O
ALTER INDEX [NombreIndice] on [Esquema].[Tabla] REBUILD

SQL Server es marca registrada de Microsoft.

sábado, 28 de junio de 2014

Trucos y Consejos para optimización de consultas y mejorar los tiempos (Rendimiento)

Desde hace muchos años trabajo en desarrollo de software y en el transcurso de ese tiempo he venido adquiriendo algunas costumbres a la hora de escribir las sentencias  SQL, algunas óptimas y otras no tan ortodoxas, a continuación se las pongo a disposición. Les recuerdo que esto es bajo su propia responsabilidad.

Aquí encontrarás las diferentes formas de hacer consultas con parámetros  dinámicos y la manera de optimizar y mejorar los tiempos de consulta.

1.       La primera parte es la optimización de los campos durante el diseño de la tabla. Utiliza el tipo de campo necesario para almacenar el valor. Por ejemplo si necesito almacenar una fecha “20/11/2014”, utilizo un campo Date en vez del DateTime. Si el campo va a almacenar un texto utiliza un NVarChar(n) con un “n” que corresponda a un valor ligeramente mayor al tamaño máximo esperado, procuró nunca usar el NVarChar(Max).
2.       Trato  de tener cuidado con la creación de los índices, generalmente al inicio del sistema los coloco solo en los campos necesarios, como costumbre tengo el usar identificadores únicos de registro como llave de los datos mediante el uso de “IDENTITY”, esto hace necesario la creación de un índice adicional único por la llave de los datos. Por ejemplo, si estamos hablando de cuentas de un banco la llave natural de los datos sería el tipo y el número de la cuenta, si fuesen personas la clave natural sería el tipo y el número del documento. Para mí los índices dependen más del tipo de sistema, si es para registrar información más que para consultarla, el uso de índices debe ser mínimo.
3.       La lectura (interpretación) de un código de consulta es más sencillo si uno sigue ciertos parámetros, por ejemplo: Al momento de hacer una sentencia SQL, ubico un solo campo por línea, esto facilita la lectura de la sentencia:
Así no: Select dCliente, NombreCliente, TipoIdentificacion, Identificacion ,Direccion, Correo, EsActivo, CreadoPor, FecCreacion, ModificadoPor, FecModificacion From Cliente
Es mejor así:
Select IdCliente
      ,NombreCliente
      ,TipoIdentificacion
      ,Identificacion
      ,Direccion
      ,Correo
      ,EsActivo
      ,CreadoPor
      ,FecCreacion
      ,ModificadoPor
      ,FecModificacion
From Cliente

4.       A diferencia de los ejemplos que encuentro en internet No escribo las comas al final del campo, para mi es mejor escribirlas al comienzo, esto facilita  la actualización, cuando necesito quitar un campo, basta con agregar el carácter de comentario “--”al inicio del campo.
Select IdCliente
      ,NombreCliente
      ,TipoIdentificacion
      ,Identificacion
      ,Direccion
      ,Correo
      ,EsActivo
      --,CreadoPor
      --,FecCreacion
      --,ModificadoPor
      --,FecModificacion
From Cliente

5.       Cuando inicio la elaboración de una consulta utilizo el asterisco “*”, que me trae todos los campos, posteriormente lo sustituyo por los nombres de los campos necesarios, nunca lo dejo al final, esto impactaría demasiado en el rendimiento de la BD.
Select * From Cliente --Esto no se debe hacer
Es más optimo así:
Select IdCliente
      ,NombreCliente
      ,TipoIdentificacion
      ,Identificacion
      ,Direccion
      ,Correo
      ,EsActivo
      ,CreadoPor
      ,FecCreacion
      ,ModificadoPor
      ,FecModificacion
From Cliente

6.       Utilizo  alias para los nombres de las tablas, es más rápido para escribir y si utiliza un editor de sentencias con “IntelliSense”. Es más fácil encontrar los campos.
Select CL.IdCliente
      ,CL.NombreCliente
      ,CL.TipoIdentificacion
      ,CL.Identificacion
      ,CL.Direccion
      ,CL.Correo
      ,CL.EsActivo
      ,CL.CreadoPor
      ,CL.FecCreacion
      ,CL.ModificadoPor
      ,CL.FecModificacion
From Cliente CL

7.       Cuando comienzo a escribir las validaciones de un Where, siempre comienzo con la línea 1=1, su resultado es siembre True. Esto facilita el agregar nuevas líneas y la depuración de los comandos. Si en el momento de estar elaborando un Select complejo, necesitas quitar alguno de los parámetros es más fácil comentar la línea del parámetro a quitar.
Select CL.IdCliente
      ,CL.NombreCliente
      ,CL.TipoIdentificacion
      ,CL.Identificacion
      ,CL.Direccion
      ,CL.Correo
      ,CL.EsActivo
      ,CL.CreadoPor
      ,CL.FecCreacion
      ,CL.ModificadoPor
      ,CL.FecModificacion
From Cliente CL
Where 1=1
      --And CL.EsActivo = 1
      And CL.CreadoPor = 'Administrador'

8.       Hace algún tiempo necesitaba leer la estructura de una tabla sin la necesidad de traer datos, para esto comencé a utilizar la sentencia: Select * From DigitalTP.Cliente Where IdCliente=-1, Esto permite tener la estructura de columnas y sus tipos de datos, pero hacia un pique al índice de la llave (consulta al índice), encontré que es más eficiente usar: Select * From DigitalTP.Cliente Where 1=2

9.       Cuando empiezo la elaboración de un procedimiento almacenado, declaro los parámetros y le asigno valores predeterminados mientras elaboro la sentencia SQL. Si la consulta es a una tabla con demasiados registros, al ejecutarla las primeras veces esta puede demorarse, para evitar esto  le escribo un TOP al principio de la consulta. Una vez finalizado el procedimiento, quito los valores predeterminados y el TOP.  Para el momento de la implementación coloco al inicio del Script una validación para saber si el procedimiento ya existe, eliminarlo y volver a crearlo, esto facilita las actualizaciones a los servidores de producción.

Mientras elaboro y evaluó la consulta:

Declare @CreadoPor NVarchar(50) = 'Administrador'
Declare @EsActivo Int = 1

Select Top 1000 CL.IdCliente
      ,CL.NombreCliente
      ,CL.TipoIdentificacion
      ,CL.Identificacion
      ,CL.Direccion
      ,CL.Correo
      ,CL.EsActivo
      ,CL.CreadoPor
      ,CL.FecCreacion
      ,CL.ModificadoPor
      ,CL.FecModificacion
From Cliente CL
Where 1=1
      And CL.EsActivo = @EsActivo
   And CL.CreadoPor = @CreadoPor

Cuando ya tengo listo el procedimiento para enviar a producción.

If (select Count(*) from sysobjects where type='P' and name='[uspCliente_Consultar')>0
BEGIN
      DROP PROCEDURE dbo.[uspCliente_Consultar];
END
GO

CREATE PROCEDURE [dbo].[uspCliente_Consultar] 
                         @CreadoPor NVarchar(50)
                        ,@EsActivo Int
AS 
BEGIN 

Select CL.IdCliente
      ,CL.NombreCliente
      ,CL.TipoIdentificacion
      ,CL.Identificacion
      ,CL.Direccion
      ,CL.Correo
      ,CL.EsActivo
      ,CL.CreadoPor
      ,CL.FecCreacion
      ,CL.ModificadoPor
      ,CL.FecModificacion
From Cliente CL
Where 1=1
      And CL.EsActivo = @EsActivo
      And CL.CreadoPor = @CreadoPor
End


10.   Cuando la base de datos es muy grande, en ocasiones  elaboro procedimientos almacenados genéricos para algunas consultas, los cuales pueden responder a múltiples necesidades, estas reciben múltiples parámetros y filtran los datos por los parámetros que traen valores, lo anterior hace que el uso de los parámetros del Where  sea más delicado. Para esto hay varias maneras de configurar las consultas, aquí describiré a continuación las que conozco:

Una manera rápida, es adicionar una validación al parámetro de tal manera que si viene con un valor nulo no se tenga en cuenta para la búsqueda de registros, Esto es rápido de hacer aunque degrada el desempeño de la base de datos, su uso debiese restringir a tablas de poco tamaño Ejemplo:
Where 1=1
      And (@EsActivo Is Null Or CL.EsActivo = @EsActivo)
   And (@CreadoPor Is Null Or CL.CreadoPor = @CreadoPor)
Otra manera es mediante el uso de la instrucción  COALESCE
Where 1=1
      And CL.EsActivo=COALESCE(@EsActivo, EsActivo)
      And CL.CreadoPor=COALESCE(@CreadoPor, CL.CreadoPor)
11.   Existe otra manera que consiste en la elaboración de una consulta con las sentencias del Where  dinámicas, que filtren la información de los parámetros que traen valores y ejecutar la consulta mediante el comando Exec. Hacer la consulta así, es rápido, pero evita que el motor de la BD pueda armar planes de ejecución y abre una puerta a inyecciones de SQL.

Declare @IdCliente int=Null
Declare @FK_TipoIdentificacion int=Null
Declare @Identificacion nvarchar(128)=Null
Declare @NombreCliente nvarchar(256)='Gustavo Molina'
Declare @Contacto nvarchar(128)=Null
Declare @CargoContacto nvarchar(128)=Null
Declare @Ciudad nvarchar(50)=Null
Declare @Direccion nvarchar(256)=Null
Declare @Correo nvarchar(256)=Null
Declare @Movil nvarchar(128)=Null
Declare @Telefono nvarchar(128)=Null
Declare @EsActivo int=Null
Declare @CreadoPor nvarchar(50)=Null
Declare @FecCreacion date=Null
Declare @ModificadoPor nvarchar(50)=Null
Declare @FecModificacion date=Null


Declare @Comilla NVarchar(1) = Char(39)
Declare @SqlExec as NVarchar(Max)

       Set @SqlExec = '
       Select   CL.IdCliente
                    ,CL.FK_TipoIdentificacion
                    ,CL.Identificacion
                    ,CL.NombreCliente
                    ,CL.Contacto
                    ,CL.CargoContacto
                    ,CL.Ciudad
                    ,CL.Direccion
                    ,CL.Correo
                    ,CL.Movil
                    ,CL.Telefono
                    ,CL.EsActivo
                    ,CL.CreadoPor
                    ,CL.FecCreacion
                    ,CL.ModificadoPor
                    ,CL.FecModificacion
       From DigitalTP.Cliente CL
       Where 1=1 '

       If(@IdCliente Is Not Null)
             Set @SqlExec = @SqlExec + ' And IdCliente = @IdCliente'
       If(@FK_TipoIdentificacion Is Not Null)
             Set @SqlExec = @SqlExec + ' And FK_TipoIdentificacion = @FK_TipoIdentificacion'
       If(@Identificacion Is Not Null)
             Set @SqlExec = @SqlExec + ' And Identificacion = ' + @Comilla + @Identificacion + @Comilla
       If(@NombreCliente Is Not Null)
             Set @SqlExec = @SqlExec + ' And NombreCliente = ' + @Comilla + @NombreCliente + @Comilla
       If(@Contacto Is Not Null)
             Set @SqlExec = @SqlExec + ' And Contacto = ' + @Comilla + @Contacto + @Comilla
       If(@CargoContacto Is Not Null)
             Set @SqlExec = @SqlExec + ' And CargoContacto = ' + @Comilla + @CargoContacto + @Comilla
       If(@Ciudad Is Not Null)
             Set @SqlExec = @SqlExec + ' And Ciudad = ' + @Comilla + @Ciudad + @Comilla
       If(@Direccion Is Not Null)
             Set @SqlExec = @SqlExec + ' And Direccion = ' + @Comilla + @Direccion + @Comilla
       If(@Correo Is Not Null)
             Set @SqlExec = @SqlExec + ' And Correo = ' + @Comilla + @Correo + @Comilla
       If(@Movil Is Not Null)
             Set @SqlExec = @SqlExec + ' And Movil =' + @Comilla + @Movil + @Comilla
       If(@Telefono Is Not Null)
             Set @SqlExec = @SqlExec + ' And Telefono = ' + @Comilla + @Telefono + @Comilla
       If(@EsActivo Is Not Null)
             Set @SqlExec = @SqlExec + ' And EsActivo = ' + @Comilla + @EsActivo + @Comilla
       If(@CreadoPor Is Not Null)
             Set @SqlExec = @SqlExec + ' And CreadoPor = ' + @Comilla + @CreadoPor + @Comilla
       If(@FecCreacion Is Not Null)
             Set @SqlExec = @SqlExec + ' And FecCreacion = ' + @Comilla + Cast(@FecCreacion as nVarchar) + @Comilla
       If(@ModificadoPor Is Not Null)
             Set @SqlExec = @SqlExec + ' And ModificadoPor ' + @Comilla + @ModificadoPor + @Comilla
       If(@FecModificacion Is Not Null)
             Set @SqlExec = @SqlExec + ' And FecModificacion ='+ @Comilla + Cast(@FecModificacion as NVarchar) + @Comilla

       Exec (@SqlExec)
12.   La última que conozco y tal vez la más versátil es la de utilizar el comando “Exec sp_executesql”, este comando permite la ejecución de un SELECT dinámico que acepta parámetros y adicionalmente arma planes de ejecución.   A diferencia del Exec, evita las inyecciones de SQL y es más óptimo para el motor de la BD. A continuación les dejo un ejemplo con uso de parámetros múltiples.
CREATE PROCEDURE [dbo].[uspCliente_Consultar] 
                     @IdCliente int=Null
                    ,@FK_TipoIdentificacion int=Null
                    ,@Identificacion nvarchar(128)=Null
                    ,@NombreCliente nvarchar(256)=Null
                    ,@Contacto nvarchar(128)=Null
                    ,@CargoContacto nvarchar(128)=Null
                    ,@Ciudad nvarchar(50)=Null
                    ,@Direccion nvarchar(256)=Null
                    ,@Correo nvarchar(256)=Null
                    ,@Movil nvarchar(128)=Null
                    ,@Telefono nvarchar(128)=Null
                    ,@EsActivo int=Null
                    ,@CreadoPor nvarchar(50)=Null
                    ,@FecCreacion date=Null
                    ,@ModificadoPor nvarchar(50)=Null
                    ,@FecModificacion date=Null

AS 
BEGIN 

       Declare @SqlExec as NVarchar(Max)
       Declare @SqlParametros as NVarchar(3000)=','

Set @SqlParametros = '@IdCliente int,@FK_TipoIdentificacion int,@Identificacion nvarchar(128),@NombreCliente nvarchar(256),@Contacto nvarchar(128),@CargoContacto nvarchar(128),@Ciudad nvarchar(50),@Direccion nvarchar(256),@Correo nvarchar(256),@Movil nvarchar(128),@Telefono nvarchar(128),@EsActivo int,@CreadoPor nvarchar(50),@FecCreacion date,@ModificadoPor nvarchar(50),@FecModificacion date'

       Set @SqlExec = '
       Select   CL.IdCliente
                    ,CL.FK_TipoIdentificacion
                    ,CL.Identificacion
                    ,CL.NombreCliente
                    ,CL.Contacto
                    ,CL.CargoContacto
                    ,CL.Ciudad
                    ,CL.Direccion
                    ,CL.Correo
                    ,CL.Movil
                    ,CL.Telefono
                    ,CL.EsActivo
                    ,CL.CreadoPor
                    ,CL.FecCreacion
                    ,CL.ModificadoPor
                    ,CL.FecModificacion
       From DigitalTP.Cliente CL
       Where 1=1 '
If(@IdCliente Is Not Null)
   Set @SqlExec = @SqlExec + ' And IdCliente = @IdCliente'
If(@FK_TipoIdentificacion Is Not Null)
   Set @SqlExec=@SqlExec + ' And FK_TipoIdentificacion=FK_TipoIdentificacion'
If(@Identificacion Is Not Null)
   Set @SqlExec = @SqlExec + ' And Identificacion = @Identificacion'
If(@NombreCliente Is Not Null)
   Set @SqlExec = @SqlExec + ' And NombreCliente = @NombreCliente'
If(@Contacto Is Not Null)
   Set @SqlExec = @SqlExec + ' And Contacto = @Contacto'
If(@CargoContacto Is Not Null)
   Set @SqlExec = @SqlExec + ' And CargoContacto = @CargoContacto'
If(@Ciudad Is Not Null)
   Set @SqlExec = @SqlExec + ' And Ciudad = @Ciudad'
If(@Direccion Is Not Null)
   Set @SqlExec = @SqlExec + ' And Direccion = @Direccion'
If(@Correo Is Not Null)
   Set @SqlExec = @SqlExec + ' And Correo = @Correo'
If(@Movil Is Not Null)
   Set @SqlExec = @SqlExec + ' And Movil = @Movil'
If(@Telefono Is Not Null)
   Set @SqlExec = @SqlExec + ' And Telefono = @Telefono'
If(@EsActivo Is Not Null)
   Set @SqlExec = @SqlExec + ' And EsActivo = @EsActivo'
If(@CreadoPor Is Not Null)
   Set @SqlExec = @SqlExec + ' And CreadoPor = @CreadoPor'
If(@FecCreacion Is Not Null)
   Set @SqlExec = @SqlExec + ' And FecCreacion = @FecCreacion'
If(@ModificadoPor Is Not Null)
   Set @SqlExec = @SqlExec + ' And ModificadoPor = @ModificadoPor'
If(@FecModificacion Is Not Null)
   Set @SqlExec = @SqlExec + ' And FecModificacion = @FecModificacion'

Exec sp_executesql  @SqlExec
                    ,@SqlParametros
,@IdCliente
,@FK_TipoIdentificacion
,@Identificacion
,@NombreCliente
,@Contacto
,@CargoContacto
,@Ciudad
,@Direccion
,@Correo
,@Movil
,@Telefono
,@EsActivo
,@CreadoPor
,@FecCreacion
,@ModificadoPor
,@FecModificacion
End


Si las opiniones aquí expresadas de fueron de tu interés o no te parecen adecuadas, por favor deja un comentario o dale un ( G+1 ) si no tienes mucho tiempo.

Entrada destacada

Arquitectura de N-Capas con Visual Studio .NET y AngularJS

Este artículo es el primero de una serie de artículos en que quiero explicar mi visión de la programación por capas. La Arquitectura ...