De acuerdo a una investigación realizada en interne un generador de código permite agilizar el desarrollo de aplicaciones o proyectos de base de datos. Esto se hace con el propósito de ahorrar tiempo y a la vez programar dentro de todo algo, es una buena forma de no caer en la típica programación con toda la lógica pegada a la interfaz al estilo VB6 cuando necesitas hacer algo rápido. Así queda algo elegante sin que ello nos involucre horas y horas de programar capas. Todo esto empezó hace mucho tiempo desde que empezó a tratar de trabajar o desarrollar aplicaciones que trabajan con datos y se dieron cuenta que era muy tedioso eso de ir escribiendo todo el código para realizar un simple select, insert, update o delete, sobretodo si la tabla con la que estaba trabajando tenía como 30 campos o más, entonces la pregunta del millón ¿Habrá alguna forma de facilitar este trabajo o que tipo de acción se quiere ejecutar sobre cierta tabla?
Algunas personas al tener la herramienta de Internet trataron de realizar búsquedas de información al respecto no encontrándose mayor cosa por lo que se procedió a trabajar para desarrollar uno por si mismo.
El resultado es una clase que primero se hizo para una aplicación desarrollada en Visual Basic 6.0 y funcionó y ahora se transformo a VB.NET, el código es:
Option Strict Off
Imports System.Data.SqlClient
''' <summary>
''' Encapsula métodos necesarios para obtener información
''' interna de tablas de SQL Server.
''' </summary>
''' <remarks>Victor Viscarra © 2007</remarks>
Public Class CN_SQL
Private cs As String
Public Enum SQLTYPE
eSelect
eInsert
eUpdate
eDelete
End Enum
Public Sub New(ByVal CadenaConexion As String)
cs = CadenaConexion
End Sub
''' <summary>
''' Obtiene la lista de campos que contiene una tabla.
''' </summary>
''' <param name=Tabla">Nombre de la tabla.</param>"
Private Function GetListaCampos(ByVal Tabla As String) As DataTable
Dim dt As New DataTable
Dim sql As String
Dim cpk As Integer
sql = "select a.name as Nombre, cast(a.colorder as int) as Orden,"
sql += " cast(b.name as varchar) as Tipo,"
sql += " Length = "
sql += " case"
sql += " when b.name = 'char' or b.name = 'varchar' then cast(a.length as int)"
sql += " else cast(a.xprec as int)"
sql += " end,"
sql += "'' as Descripcion, 0 as isPK, a.isNullable,"
sql += " isIdentity = "
sql += " case"
sql += " when a.autoval is null then 0"
sql += " else 1"
sql += " end"
sql += " from syscolumns a inner join systypes b"
sql += " on (a.xtype = b.xtype and a.xusertype = b.xusertype)"
sql += " where a.id = (object_id(N'[dbo].[{0}]'))"
sql += " order by colorder"
sql = String.Format(sql, Tabla)
Try
Dim da As New SqlDataAdapter(sql, cs)
da.Fill(dt)
' Llena los datos de descripción y primary key.
If Not dt Is Nothing Then
For Each dr As DataRow In dt.Rows
dr("Descripcion") = Me.GetDesCampo(Tabla, dr("Nombre").ToString)
dr("isPK") = Me.IsPKCampo(Tabla, dr("Nombre").ToString)
If CInt(dr("isPK")) = 1 Then cpk += 1
Next
End If
Catch ex As Exception
Throw ex
End Try
Return dt
End Function
''' <summary>
''' Obtiene la descripción de un campo de la Base de Datos.
''' </summary>
''' <param name=Tabla">Nombre de la tabla propietaria del campo</param>"
''' <param name=Campo">Campo del que se quiere obtener la descripción</param>"
Private Function GetDesCampo(ByVal Tabla As String, ByVal Campo As String) As String
Dim sql As String
Dim ret As String = Nothing
Dim o As Object
Dim cn As New SqlConnection(cs)
sql = "select value from ::fn_listextendedproperty ('MS_Description','user','dbo','table',"
sql += "'{0}','column','{1}')"
sql = String.Format(sql, Tabla, Campo)
Try
Dim cm As New SqlCommand
cn.Open()
With cm
.Connection = cn
.CommandType = CommandType.Text
.CommandText = sql
.ExecuteNonQuery()
o = .ExecuteScalar()
End With
If Not o Is Nothing Then
ret = o.ToString()
End If
Catch ex As Exception
If TypeOf ex Is InvalidCastException Then
ret = Nothing
Else
Throw ex
End If
Finally
If cn.State <> ConnectionState.Open Then
cn.Close()
End If
cn.Dispose()
End Try
Return ret
End Function
''' <summary>
''' Obtiene un valor que indica si un campo forma parte del Primary Key
''' de la tabla de acuerdo al parámetro pasado.
''' </summary>
''' <param name=Tabla">Nombre de la tabla propietaria del campo</param>"
''' <param name=Campo">Campo del que se quiere obtener la información</param>"
Private Function IsPKCampo(ByVal Tabla As String, ByVal Campo As String) As Integer
Dim ret As Integer
Dim c As String = String.Empty
Dim sql As String
Dim o As Object
Dim cn As New SqlConnection(cs)
sql = "select 'T' from sysindexkeys ik, sysindexes i"
sql += " Where ik.id = i.id"
sql += " and ik.indid = i.IndId"
sql += " and ik.colid = (select colid from syscolumns"
sql += " where id = (object_id(N'[dbo].[{0}]'))"
sql += " and name = '{1}')"
sql += " and i.id = (object_id(N'[dbo].[{0}]'))"
sql += " and i.name in (SELECT name"
sql += " From sysobjects"
sql += " where (xtype = 'PK'))"
sql = String.Format(sql, Tabla, Campo)
Try
Dim cm As New SqlCommand
cn.Open()
With cm
.Connection = cn
.CommandType = CommandType.Text
.CommandText = sql
o = .ExecuteScalar()
End With
If Not o Is Nothing Then
c = o.ToString()
End If
If c = "T" Then ret = 1
Catch ex As Exception
If TypeOf ex Is InvalidCastException Then
ret = 0
Else
Throw ex
End If
Finally
If cn.State <> ConnectionState.Open Then
cn.Close()
End If
cn.Dispose()
End Try
Return ret
End Function
''' <summary>
''' Genera una Sentencia SQL (DML) de acuerdo al nombre de la tabla y tipo
''' que se desee.
''' </summary>
''' <param name=Tabla">Nombre de la tabla</param>"
''' <param name=TipoDML">Tipo de DML que se quiere obtener</param>"
Public Function GeneraSQL(ByVal Tabla As String, ByVal TipoDML As SQLTYPE) As String
Dim i, controlPK, fc As Integer
Dim sql As String = String.Empty
Dim sql2 As String
Dim dt As DataTable
' Obtiene todos los datos necesarios de cada
' campo existente de la tabla
Try
dt = Me.GetListaCampos(Tabla)
Catch ex As Exception
dt = Nothing
Throw ex
End Try
If Not dt Is Nothing Then
fc = dt.Rows.Count - 1
Select Case TipoDML
Case SQLTYPE.eSelect
' Genera la cadena SQL <<Select>>
sql = "SELECT "
For Each dr As DataRow In dt.Rows
sql += dr("Nombre")
If i < fc Then
sql += ", "
i += 1
Else
sql += vbCrLf + "FROM {0}"
End If
Next
Case SQLTYPE.eInsert
' Genera la cadena SQL <<Insert Into>>
sql = "INSERT INTO {0}" + vbCrLf + " ("
sql2 = "VALUES" + vbCrLf + " ("
For Each dr As DataRow In dt.Rows
If dr("isIdentity") = 0 Then
sql += dr("Nombre")
sql2 += "@" + dr("Nombre")
If i < fc Then
sql += ", "
sql2 += ", "
Else
sql += ")"
sql2 += ")"
sql += vbCrLf + sql2
End If
End If
i += 1
Next
Case SQLTYPE.eUpdate
' Genera la cadena SQL <<Update>>
sql = "UPDATE {0}" + vbCrLf + "SET "
controlPK = 0
For Each dr As DataRow In dt.Rows
If dr("isPK") = 0 Then
controlPK += 1
sql += dr("Nombre") + " = @" + dr("Nombre")
If i < fc Then
sql += ", " + vbCrLf
Else
sql += vbCrLf + "WHERE "
End If
End If
i += 1
Next
If controlPK = 0 Then
sql = "NO SE PUEDE GENERAR EL COMANDO UPDATE PARA LA TABLA {0}"
sql += " DEBIDO A QUE NO POSEE CAMPOS ACTUALIZABLES."
sql = String.Format(sql, Tabla)
Throw New Exception(sql)
End If
controlPK = 0
i = 0
For Each dr As DataRow In dt.Rows
If CInt(dr("isPK")) = 1 Then
controlPK += 1
sql += dr("Nombre") + " = @" + dr("Nombre")
sql += vbCrLf + " AND "
End If
Next
If controlPK = 0 Then
sql = "NO SE PUEDE GENERAR EL COMANDO UPDATE PARA LA TABLA {0}"
sql += " DEBIDO A QUE NO POSEE PRIMARY KEY."
sql = String.Format(sql, Tabla)
Throw New Exception(sql)
Exit Select
End If
sql = sql.Substring(0, sql.Length - 7)
Case SQLTYPE.eDelete
' Genera la cadena SQL <<Delete>>
sql = "DELETE FROM {0}"
sql += vbCrLf + "WHERE "
controlPK = 0
For Each dr As DataRow In dt.Rows
If CInt(dr("isPK")) = 1 Then
controlPK += 1
sql += dr("Nombre") + " = @" + dr("Nombre")
sql += vbCrLf + " AND "
End If
Next
If controlPK = 0 Then
sql = "NO SE PUEDE GENERAR EL COMANDO UPDATE PARA LA TABLA {0}"
sql += " DEBIDO A QUE NO POSEE PRIMARY KEY."
sql = String.Format(sql, Tabla)
Throw New Exception(sql)
Exit Select
End If
sql = sql.Substring(0, sql.Length - 7)
End Select
If Not String.IsNullOrEmpty(sql) Then
sql = String.Format(sql, Tabla)
End If
End If
Return sql
End Function
End Class