Scripts útiles - Sql Server

Buenas! Continuando con el post anterior, hoy les dejo algunos scripts muy sencillos para Sql Server, pero que siempre vienen bien.

Son muy útiles. A mi me han servido.

Buscar un campo en una todas las tablas:

SELECT TABLE_NAME,*
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%NombreDeCampo%'


Buscar un Stored Procedure por algun fragmento del nombre:

SELECT ROUTINE_NAME, ROUTINE_DEFINITION, *
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%palabraDelStored%'
AND ROUTINE_TYPE='PROCEDURE'


Buscar Stored Procedures por texto:

SELECT distinct

name SP_Name

FROM [sysobjects] INNER JOIN [syscomments] ON

[sysobjects].id = [syscomments].id

where xtype = 'P'

and text like '%textoabucar%'



Espero que les venga bien! Saludos!

Buscar FKs - Relaciones de Tablas - Sql Server

Hoy les dejo un post que les puede resultar muy útil.

A mi me ha sacado de más de un apuro.

Suele pasar que a veces trabajamos con bases de datos muy grandes, o que estén mal diseñadas o que simplemente no entendemos por completo su esquema. A mi me ha pasado en el trabajo con una base de datos diseñada fuera de Raona.

En trabajos como este necesitamos buscar información determinada, y nos pasamos recorriendo tablas y tablas.

Para evitar esto les dejo un script SQL, para SQL Server, para encontrar tablas con FKs que apuntan a una tabla que nosotros queramos. Este script nos devuelve la tabla donde se encuentra la clave foránea, la columna de la FK y además el nombre de la constraint.

-- RELACION DE TABLA (DEPENDENCIAS)

SELECT
FK_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME,
ConstraintName = C.CONSTRAINT_NAME
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN
INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN
INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN
(
SELECT
TC.TABLE_NAME, CU.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON TC.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
WHERE TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT
ON PT.TABLE_NAME = PK.TABLE_NAME
WHERE
PK.TABLE_NAME = 'SALESORDERHEADER' -- TU TABLA



Espero sinceramente que le sirva a alguien!

ItextSharp - Escribiendo PDF en .Net

La semana pasada tuve que trabajar en una aplicación que generara un reporte en formato PDF, con datos obtenidos de una BBDD.

Es algo muy útil y práctico.

A continuación les dejo una explicación de cómo pueden generar archivos PDF desde .Net utilizando la biblioteca itextsharp que la pueden usar en forma gratuita.

Let's go!

Primero, añadimos a nuestro proyecto una referencia a esta biblioteca (este paso no lo voy a explicar ya que es muy sencillo, si alguien no sabe como hacerlo que me pregunte).

Ahora agregamos a nuestro código:

using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;


namespace PDFApp
{
public class Query
{
public static XmlDocument ExecuteQuery(SqlCommand cmd, ref SqlTransaction trans)
{
if( cmd == null )
throw new ArgumentNullException("cmd", "El comando no puede ser null.");
if( trans == null )
throw new ArgumentNullException("trans", "La transaccion no puede ser null.");

XmlNode xmlrow = null;
XmlReader xmlreader = null;
XmlDocument xmldoc = null;
xmldoc = new XmlDocument();
xmldoc.LoadXml("");
xmlreader = cmd.ExecuteXmlReader();
xmlrow = xmldoc.ReadNode(xmlreader);
while ( xmlrow != null )
{
xmldoc.DocumentElement.AppendChild(xmlrow);
xmlrow = xmldoc.ReadNode(xmlreader);
}
xmlreader.Close();
return xmldoc;
}
public static XmlDocument ExecuteQuery(SqlCommand cmd, SqlConnection conn)
{
XmlDocument xmldoc = null;
SqlTransaction trans = null;
if ( conn != null )
{
if ( conn.State != ConnectionState.Open )
{
conn.Open();
}
cmd.Connection = conn;
}
else
{
throw new ArgumentNullException("cmd", "El comando no puede ser null.");
}
trans = cmd.Connection.BeginTransaction();
xmldoc = new XmlDocument();
xmldoc.LoadXml("");
try
{
cmd.Transaction = trans;
xmldoc = ExecuteQuery(cmd, ref trans);
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
return xmldoc;
}
}


Y ahora ponemos lo siguiente en el código del evento de un botón de nuestra página.

Document document = new Document(PageSize.A4, 90f, 50f, 90f, 60f);
try
{
XmlDocument Doc = new XmlDocument();
SqlConnection cnx = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=BASEDEDATOS;Data Source=SERVIDORSQL");

//Este es un ejemplo que toma datos de una tabla personas,
//Es muy importante poner "for xml raw !!!
SqlCommand cmd = new sqlcommand("select * from personas for xml raw");

cmd.Connection = cnx;
Doc = Query.ExecuteQuery(cmd, cnx);

// Configuración del documento PDF

string FullPathOut = "c:\\SalidaPDF.pdf";
PdfWriter.getInstance(document, new filestream(fullpathout, filemode.create));

// Fonts y colores

Font font_celdas = FontFactory.getFont(FontFactory.HELVETICA, 8, Font.NORMAL);
Font font_titulo_tabla = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.BOLD,
new Color(255,255,255));
Color color_negro = new color(0, 0, 0);
document.Open();
Table table = new Table(3);
table.BorderWidth = 0;
table.BorderColor = color_negro;
table.Padding = 1;
table.Spacing = 1;
Cell titulo = new cell(new Phrase("Datos de la tabla", font_titulo_tabla));
titulo.Header = true ;
titulo.BackgroundColor = color_negro;
titulo.Colspan = 3;
table.addCell(titulo);
table.addCell(new Phrase("Nombre", font_celdas));
table.addCell(new Phrase("Num. Documento", font_celdas));
table.addCell(new Phrase("Teléfono", font_celdas));
table.endHeaders();
foreach(xmlelement elem in Doc.SelectNodes("/ROOT/row"))
{
table.addCell(new Phrase(Elem.GetAttribute("Columna1"), font_celdas));
table.addCell(new Phrase(Elem.GetAttribute("Columna2"), font_celdas));
table.addCell(new Phrase(Elem.GetAttribute("Columna3"), font_celdas));
}
document.Add(table);
}

catch (XmlException xex)
{
throw new Exception(xex.Message);
}
catch (DocumentException de)
{
throw new Exception(de.Message);
}
catch (IOException ioe)
{
throw new Exception(ioe.Message);
}
finally
{
document.Close();
}
}
}
}




Espero que les sirva! En la próxima continuaré con este tema!

Saludos!

Pasar datos por método POST a terceros

Bueno, un problema que se me presentó trabajando con Asp.net fue en un sitio que tenía que pasar por método POST ciertos datos a una página de pagos electrónicos.

La forma más práctica de pasar datos entre páginas aspx con el método POST es la que se detalla en esta página de forma sencilla:

NetCodigo.webinfo.es

Ahora, esto en el caso que yo describo no sirve, ya que no soy yo quien maneja los datos en la página destino, sino un tercero que espera que se los mande por POST.

Para solucionar esto escribí la siguiente clase, si alguno de ustedes se les presenta el mismo problema no tienen más que copiar/pegar el siguiente código (y después leerlo, obviamente jeje)


using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

/// <summary>
/// Esta clase genera los formularios para mandar por post los datos a otras páginas
/// </summary>
public class RemotePost
{
    System.Collections.Specialized.NameValueCollection _Inputs = new System.Collections.Specialized.NameValueCollection();
    string _Url = "";
    string _Method = "post";
    string _FormName = "form1";<

    /// <summary>
    /// Devuelve o setea la url del medio de pago
    /// </summary>
    public string Url
    {
        get {return _Url;}
        set {_Url = value;}
    }

    /// <summary>
    /// Agrega inputs hidden al formulario
    /// </summary>
    /// <param name="name"></param>
    /// <param name="value"></param>
    public void Add(string name, string value)
    {
        _Inputs.Add(name,value);
    }
  
    /// <summary>
    /// Imprime en el cliente el formulario de compra
    /// </summary>
    public void Post()
    {
        System.Web.HttpContext.Current.Response.Clear();
        System.Web.HttpContext.Current.Response.Write("");
        System.Web.HttpContext.Current.Response.Write(String.Format("< html >< head >< /head >< body onload="\" >", _FormName));
        System.Web.HttpContext.Current.Response.Write(String.Format("<center><form target="\" name="\" method="\" action="\">", _FormName, _Method, Url));

        for (int i = 0; i < _Inputs.Keys.Count; i++)
        {
            System.Web.HttpContext.Current.Response.Write(String.Format("<input name="\" type="\" value="\">", _Inputs.Keys[i], _Inputs[_Inputs.Keys[i]]));
        }
        System.Web.HttpContext.Current.Response.Write("</form></center></body></html>")
    }
}



Bien, ¿y cómo se usa esto?

protected void Button1_Click(object sender, EventArgs e)
{
RemotePost myremotepost = new RemotePost();
myremotepost.Url = "URL DE DESTINO";
myremotepost.Add("NombreItem", "ValorItem");
myremotepost.Add("NombreItem2", "ValorItem2");
myremotepost.Add("NombreIntem3", "ValorItem3");
myremotepost.Post();
}


Espero que esto les pueda servir! Cualquier duda consulten!

Espero sus comentarios!

Saludos!

Un pequeño post de humor hoy,

Siempre viene bien un momento de distracción!



Saludos!

Carrito de compras

Un trabajo que tuve que hacer en la universidad fue un sitio de ventas de artículo electrónicos.

Una buena implementación de un carrito son las variables de sesión (siempre que no se quiera un carrito persistente obviamente).

Lo recomendable siempre en este tipo de sitios es tener un modelo de tres capas, separando diseño, lógica y acceso a datos.

Visto de este modo necesitaremos una clase que maneje la lógica de negocios del carrito.

Para acceder a las variables de sesión desde una clase se debe usar lo siguiente:

HttpContext.Current.Session["NombreClave"]


También un punto a no olvidar es que hay que establecer en el archivo global.asax que al inicio de cada sesión el carrito no tiene productos cargardos.
void Session_Start(object sender, EventArgs e)
{
Session.Clear();
Session["TotalArts"] = 0;
}


Bueno, sin más, les dejo el código de nuestra clase para la lógica del carrito de compras:
using System;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Web.SessionState;
using System.Collections.Generic;

///


/// Clase que maneja el carrito de compras
///


namespace BLL
{
public class ShoppingCart
{
public ShoppingCart()
{

}

///
/// Devuelve la cantidad de artículos que se van a comprar
///

public static int TotalActiveArts
{
get
{
int count = 0;

for (int i = 1; i <= Convert.ToInt32(System.Web.HttpContext.Current.Session["TotalArts"]); i++) { if (HttpContext.Current.Session["IdArt" + i.ToString()].ToString() != "0") count++; } return count; } } ///
/// Devuelve el total de los artículos guardados en sesión
///

private static int TotalArts
{
get
{
return Convert.ToInt32(System.Web.HttpContext.Current.Session["TotalArts"]);
}
}


public static void AddArtInCart(int categoryId, string name, string description, string urlImage, decimal price, int memberId)
{
HttpContext.Current.Session["TotalArts"] = TotalArts + 1;
HttpContext.Current.Session["CategoryIdArt" + TotalArts.ToString()] = categoryId;
HttpContext.Current.Session["NameArt" + TotalArts.ToString()] = name;
HttpContext.Current.Session["DescriptionArt" + TotalArts.ToString()] = description;
HttpContext.Current.Session["UrlImg" + TotalArts.ToString()] = urlImage;
HttpContext.Current.Session["PriceArt" + TotalArts.ToString()] = price;
HttpContext.Current.Session["IdArt" + TotalArts.ToString()] = 1;
}

///
/// Guarda cada uno de los artículos en la BD.
///

public static void Purchase()
{
for (int i = 1; i <= TotalArts; i++) { if (HttpContext.Current.Session["IdArt" + i.ToString()].ToString() != "0") { HttpContext.Current.Session["IdArt" + i.ToString()] = /*MÉTODO DE ALTA DE ARTÍCULO*/ ; } } } ///
/// Borra los artículos de la sesión. Devuelve un string con un mensaje al usuario.
///

///
public static string Payed()
{
string state = "Gracias";

try
{
for (int i = 1; i <= TotalArts; i++) { HttpContext.Current.Session.Remove("TotalArts"); HttpContext.Current.Session.Remove("CategoryIdArt"); HttpContext.Current.Session.Remove("NameArt"); HttpContext.Current.Session.Remove("DescriptionArt"); HttpContext.Current.Session.Remove("UrlImg"); HttpContext.Current.Session.Remove("PriceArt"); HttpContext.Current.Session.Remove("IdArt"); HttpContext.Current.Session.Remove("TotalArts"); } } catch { state = "Ha habido un problema con el registro de tu compra"; } return state; } ///
/// Devuelve la tabla con los artículos activos en la sesión
///

///
public static DataTable ShopTable()
{
DataTable dt = new DataTable();

DataColumn[] dcColumns = new DataColumn[3];

dt.Columns.Add("Id");
dt.Columns.Add("Artículo");
dt.Columns.Add("Precio");

dt.Columns.AddRange(dcColumns);

for (int i = 1; i <= TotalArts; i++) { if (HttpContext.Current.Session["IdArt" + i.ToString()].ToString() != "0") { DataRow dr = dt.NewRow(); dr["Id"] = HttpContext.Current.Session["IdArt" + i.ToString()].ToString(); dr["Artículo"] = HttpContext.Current.Session["TitleArt" + i.ToString()].ToString(); dr["Precio"] = HttpContext.Current.Session["PriceArt" + i.ToString()].ToString(); dt.Rows.Add(dr); } } return dt; } } }


Para los que estén interesados en un sitio de compras, pronto iré agregando más info útil, sobre todo enfocada a la BLL y la DAL.

Espero que les sirva!

Saludos!!

Seguridad en Asp.Net

Hola!
Uno de los primeros trabajos que tuve que hacer fue implementar la seguridad en un sitio Web.
En la universidad sólo había aprendido a manejar membresías, roles y demás sólo por código, lo que lleva cierto tiempo. Pero Visual Studio 2008 nos proporciona herramientas fantásticas para poder realizar un sitio completamente seguro, con autenticación y autorización sin practicamente tocar código.

Usaremos controles de Login y el Site Administration Tool.

Primeramente debemos crear una página de Login.

Alli insertaremos un LoginView.
Como verán este control posee dos vistas: una para el usuario anónimo y otra para el usuario autenticado.
En la vista del usuario anónimo insertaremos un control de Login, que hace nada más (ni nada menos) que pedir al usuario sus credenciales.
Ahora cambiaremos a la vista de usuario autenticado e insertaremos algún mensaje de bienvenida.

Ahora procederemos a crear una página de Registro para nuestros usuarios, donde insertaremos un CreateUserWizard, este control pide los datos necesarios para que el usuario se registre en nuestra página.

Con las páginas básicas ya creadas, vamos a proceder a insertar carpetas en nuestro sitio, en donde diferenciaremos el contenido al que pueden acceder los usuarios, según sus roles.

En este ejemplo, yo agrego las carpetas Administradores y la carpeta Usuarios.



Bien, ahora en dichos directorios agregaremos páginas y contenidos para los usuarios que pueden acceder.

Una vez hecho esto abrimos el Site Administration Tool.


Allí vamos a la pestaña de Seguridad y elegimos la opción de usar el Asistente para configurar la Seguridad paso a paso.

El paso 1 es sólo una bienvenida a la herramienta.

Paso 2: Seleccionamos Desde internet

Paso 3: Lo dejamos con la configuración que nos muestro

Paso 4: Habilitamos los roles, click en siguiente y creamos los roles Admin y Usuario.

Paso 5: Creamos el usuario admin.

Paso 6: En este paso estableceremos el acceso que tienen los roles a las carpetas.

Primero expandimos la carpeta del sitio.
Luego seleccionamos la carpeta Administradores, buscamos el rol Admin, tildamos Permitir (Allow) y clickeamos el botón para agregar la regla.

De la misma forma le denegaremos el acceso a todos los usuarios a la carpeta Admin, le permitimos a Usuarios a la carpeta Usuarios y le denegamos el acceso a esta carpeta a usuarios anónimos.

Paso 7: Finalizamos

Ahora vamos a Administrar usuarios (Manage Users) e insertamos el Usuario Admin en el rol Admin.

Salimos de la Herramienta de Administración.

Como podrán observar, en la carpeta App_Data se ha agregado la Base de Datos con nuestros usuarios, en otro post explicaré cómo transladar esta base fuera de la aplicación.

Listo!

Ya tenemos nuestro sitio seguro! Queda en ustedes agregar el contenido del sitio obviamente.

Le recomiendo que hechen un vistazo a los demás controles de Login, son extremadamente
útiles, muy prácticos y fáciles de usar.

Se habrán dado cuenta que no hemos tocado ni una sóla línea de código.
Es algo bastante básico, pero que nos ahorra tiempo a la hora de programar una aplicación.

Saludos!

Bienvenidos!

Hola!
Con este post doy inicio a mi blog.
El contenido va a estar basado principalmente en la resolución de problemas que me han surgido en la programación, ya sea como estudiante o como profesional (recientemente iniciado, pero con mucho entusiasmo) . También incluiré alguna que otra anécdota, artículos que me parezcan interesantes, e incluso algún material humorístico; que sirva como "cable a tierra" cuando uno se enreda con la programación.

Espero poder logra de esto algo ameno, y más que nada me gustaría poder aportarles algo de mis vivencias, sobre todo a estudiantes de carreras informáticas.

¿Porqué "Código DaVinci PuntoNet"?

DaVinci era un hombre adelantado a su época. Un visionario absoluto. Un genio brillante, que encontró un equilibrio entre el arte y la ciencia.
Realmente admiro el trabajo de este hombre.

Y jugando un poco con su nombre, el libro de Dan Brown, y aquello con lo que nos ensuciamos las manos todos los días: "EL CÓDIGO", surge el nombre de este blog.


Gracias! Los espero por acá!