sábado, 7 de agosto de 2010

Cual es el password predeterminado del Windows Storage Server 2008??

Como poseedor de una subscripción MSDN me descargué el Windows Storage Server 2008 e inmediatamente me armé una máquina virtual para probarlo.

El tema es que cuando finalizó la instalación me apareció la ventana de login y no tenía la menor idea cual era la pass de logueo.

Bueno, luego de arduas investigaciones (llamé a un amigo que ya lo había instalado) pude obtener la tan ansiada password: wSS2008! (el signo de admiración es parte del password también).

lunes, 16 de noviembre de 2009

Como leer un archivo pdf desde un aplicativo web form / asp.net

Aquí les dejo un método que les permitirá leer un archivo pdf (adobe) desde un aplicativo Web Asp.NET.

Deben utilizar el siguiente imports:

using System.Net;

A continuación el método:

private void LeerArchivoPdf(string NombreArchivoPDF)
{
string ruta = NombreArchivoPDF;
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(ruta);
if (buffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", buffer.Length.ToString());
Response.BinaryWrite(buffer);
}
}

Hugo Bernachea
MCT - MCSD

viernes, 16 de octubre de 2009

A namespace does not directly contain members such as fields or methods - App.Config

Si les aparece el siguiente error en el app.config:
A namespace does not directly contain members such as fields or methods
O su equivalente es castellano, y ustedes verifican y se aseguran que su app.config está correctamente configurado, si verifican el contenido del app.config un par de veces y ven que el contenido del app.config es ok, lo mejor que pueden hacer es copiar el contenido del app.config en un archivo de texto, guardar dicho archivo de texto, eliminar el app.config y volver a agregar un app.config en blanco y nuevamente copiar el contenido del app.config anterior. Con eso se suele corregir ese error.

Función IsNumeric en C#

Csharp (C#) no cuenta con una función isnumeric al estilo Visual Basic, pero se pueden implementar diferentes soluciones para lograr el objetivo, uno es hacer una función como la siguiente:

public bool IsNumeric(object Expression)
{
bool esnumero;
double returnNumero;

esnumero= Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any,System.Globalization.NumberFormatInfo.InvariantInfo, out returnNumero);
return esnumero;
}

La otra solución es crear una librería (Dll) en visual basic.NET y directamente referenciarla en C#, que yo pienso que es quizás la mejor opción.

sábado, 1 de agosto de 2009

.NET 3.5 - Usando el Nuevo tipo SqlDbType.Structured para pasar parámetros de tipo Table a Stored Procedures en SQL Server 2008

En SQL Server 2008 se ha agregado la posibilidad (largamente esperada) de pasar un parámetro de tipo Table a un Stored Procedure, pueden ver una explicación aquí:
http://sqldata.blogspot.com/2009/08/mejoras-en-t-sql-de-sql-server-2008-el.html

La pregunta es como hacer desde .NET 3.5 para invocar este tipo de stored procedures, lo cual se resuelve fácilmente con el nuevo sqltype de tipo Structured

El código que viene a continuación es un ejemplo de lo dicho, como verán todo esto es código conocido, la única novedad es que pasamos directamente un datatable completo al value del parámetro, definido como Structured, veamos el ejemplo:

//creo un data table para almacenar algunos registros de ejemplo
DataTable dtClientes = new DataTable("Clientes");
DataColumn dcNombre = new DataColumn("nombre", typeof(string));
DataColumn dcApellido = new DataColumn("apellido", typeof(string));
DataColumn dcEmail = new DataColumn("Email", typeof(string));
dtClientes.Columns.Add(dcNombre);
dtClientes.Columns.Add(dcApellido);
dtClientes.Columns.Add(dcEmail);
//agrego un cliente
DataRow drCustomer = dtClientes.NewRow();
drCustomer["nombre"] = "aaa.net";
drCustomer["apellido"] = "XYZ";
drCustomer["Email"] = "info@kyriosdata.com.ar";
dtClientes.Rows.Add(drCustomer);
//Agrego otro cliente
drCustomer = dtClientes.NewRow();
drCustomer["nombre"] = "bbb.net";
drCustomer["apellido"] = "XYZ";
drCustomer["Email"] = "info@kyriosdata.com.ar";
dtClientes.Rows.Add(drCustomer);
//Y otro cliente mas
drCustomer = dtClientes.NewRow();
drCustomer["nombre"] = "ccc.net";
drCustomer["apellido"] = "XYZ";
drCustomer["Email"] = "info@kyriosdata.com.ar";
dtClientes.Rows.Add(drCustomer);
//Creo la conexion, recuerde modificar el connection string
// y modifique server e indique SU servidor
// y modifique en base de datos e indique SU base de datos
SqlConnection conn = new SqlConnection("server=.;database=Ejemplo;Integrated Security=true");
conn.Open();
//Lo tradicional, creamos un comando que invoque al store "Agrega clientes"
// que está definido y se pueden encontrar en el enlace siguiente:
// http://sqldata.blogspot.com/2009/08/mejoras-en-t-sql-de-sql-server-2008-el.html
SqlCommand cmdCustomer = new SqlCommand("AgregaClientes", conn);
cmdCustomer.CommandType = CommandType.StoredProcedure;
//Aquí en realidad se encuentra lo único distinto con respecto
// a la lógica que veníamos usando en .NET
// y es crear el parámetro pero usando el nuevo sqldbtype Structured
// el cual puede recibir un datatable completo
// el s.p. matchea con un parámetro de tipo table, ver el link
SqlParameter paramCustomer = cmdCustomer.Parameters.Add("@ClientesTVP", SqlDbType.Structured);
paramCustomer.Value = dtClientes;
//Ejecutamos
cmdCustomer.ExecuteNonQuery();

Y si revisamos la tabla Clientes debiéramos encontrar los nuevos registros agregados a la tabla cliente.

Nuevamente y por si a alguien se le escapó el detalle, la información acerca de este nuevo tipo de parámetros como asimismo la definición del Stored Procedure se encuentra en el siguiente enlace:

http://www.sqlexperto.com.ar/index.php?topic=20.msg21#new





martes, 21 de julio de 2009

Diferencias entre Eventos y Delegados - En qué son distintos?

Eventos versus Delegados (Events vs Delegates)

Es la típica pregunta acerca de la diferencia entre eventos y delegados, considerando que uno siempre podría imitar la funcionalidad de un evento utilizando un delegado. Esto considerando que un evento siempre está relacionado a un delegado.

Un evento es parecido a un multicast delegate en algún sentido.

Veamos el siguiente ejemplo donde tenemos msgNotifier (evento) y msgNotifier2 (delegado simple) que aparentan comportarse exactamente igual en todo sentido.

using System;

namespace EventAndDelegate
{
delegate void MsgHandler(string s);

class Class1
{
public static event MsgHandler msgNotifier;
public static MsgHandler msgNotifier2;
[STAThread]
static void Main(string[] args)
{
Class1.msgNotifier += new MsgHandler(PipeNull);
Class1.msgNotifier2 += new MsgHandler(PipeNull);
Class1.msgNotifier("test");
Class1.msgNotifier2("test2");
}

static void PipeNull(string s)
{
return;
}
}
}


Si vemos el código IL para el método Main vemos que ambos msgNotifier y msgNotifier2 son usados de la misma manera.

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 95 (0x5f)
.maxstack 4
IL_0000: ldsfld class EventAndDelegate.MsgHandler EventAndDelegate.Class1::msgNotifier
IL_0005: ldnull
IL_0006: ldftn void EventAndDelegate.Class1::PipeNull(string)
IL_000c: newobj instance void EventAndDelegate.MsgHandler::.ctor(object,
native int)
IL_0011: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0016: castclass EventAndDelegate.MsgHandler
IL_001b: stsfld class EventAndDelegate.MsgHandler EventAndDelegate.Class1::msgNotifier
IL_0020: ldsfld class EventAndDelegate.MsgHandler EventAndDelegate.Class1::msgNotifier2
IL_0025: ldnull
IL_0026: ldftn void EventAndDelegate.Class1::PipeNull(string)
IL_002c: newobj instance void EventAndDelegate.MsgHandler::.ctor(object,
native int)
IL_0031: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0036: castclass EventAndDelegate.MsgHandler
IL_003b: stsfld class EventAndDelegate.MsgHandler EventAndDelegate.Class1::msgNotifier2
IL_0040: ldsfld class EventAndDelegate.MsgHandler EventAndDelegate.Class1::msgNotifier
IL_0045: ldstr "test"
IL_004a: callvirt instance void EventAndDelegate.MsgHandler::Invoke(string)
IL_004f: ldsfld class EventAndDelegate.MsgHandler EventAndDelegate.Class1::msgNotifier2
IL_0054: ldstr "test2"
IL_0059: callvirt instance void EventAndDelegate.MsgHandler::Invoke(string)
IL_005e: ret
} // end of method Class1::Main


Si vemos en el MSDN keywords list vemos que los event son solo modificadores (modifier).

La pregunta es que cosa exactamente modifican?

Valor agregado de un evento
Eventos e interfaces

Un evento puede ser incluido en la declaración de una interface mientras que un campo no.

interface ITest
{
event MsgHandler msgNotifier; // compila
MsgHandler msgNotifier2; // error CS0525: Interfaces cannot contain fields
}

class TestClass : ITest
{
public event MsgHandler msgNotifier; // cuando se implementa una interface se debe implementar el evento también.
static void Main(string[] args) {}
}


Invocation de un evento

Un evento solo puede ser invocado en la clase en la que se declaró, mientras que un delegado puede ser invocado desde cualquier parte.

Ejemplo:

using System;

namespace EventAndDelegate
{
delegate void MsgHandler(string s);

class Class1
{
public static event MsgHandler msgNotifier;
public static MsgHandler msgNotifier2;

static void Main(string[] args)
{
new Class2().test();
}
}

class Class2
{
public void test()
{
Class1.msgNotifier("test"); // error CS0070: The event 'EventAndDelegate.Class1.msgNotifier' can only appear on the left hand side of += or -= (except when used from within the type 'EventAndDelegate.Class1')
Class1.msgNotifier2("test2"); // compiles fine
}
}
}

Esta restricción es muy fuerte y aún las clases derivadas no pueden invocar dicho evento (salvo un método protected virtual que lo dispare).

Accesores de Eventos
Eventos disponen de métodos add y remove.
Esto es similar al get y set de las properties.

Firma del evento

el .NET framework agrega una restriction en la firma de los delegados que pueden ser usados como eventos. La firma tienen que ser en este estilo foo(object source, EventArgs e), donde source es el objeto que dispara el evento y e contiene información específica a este evento.

Estas serían a mi entender algunas diferencias entre eventos (events) y delegates (delegados)

domingo, 21 de junio de 2009

Como exponer los eventos RowUpdated y RowUpdating en un TableAdapter?

Bueno, después de dar un par de vueltas e investigar un poco, acá les dejo la solución a como exponer los eventos RowUpdated y RowUpdating de un TableAdapter de los generados con diseñador de Dataset fuertemente Tipados.

Tanto en C# 2005 como en C# 2008 tienen que ir al Dataset tipado (xsd).
Identifican al TableAdapter (NO el datatable) que van a modificar y clickean con boton izquierdo.
Van a la ventana de propiedades para el tableadapter y ponen la propidad ConnectionModifier en PUBLIC.

Después clickean con el botón derecho en el mismo TableAdapter y van a la opción Ver Código (View Code) y en la ventana de código agregan la clase parcial necesaria para incorporar el código que expone el dataadapter interno.

El código a continuación es un ejemplo de como debiera queda la clase

namespace WinCon.DataSet1TableAdapters //obviamente acá va el namespace de ustedes
{
using System.Data;
using System.Data.SqlClient; //acá va el provider de la base que ustedes están usando
// en caso que no sea SQL Server

public partial class EjemploTableAdapter //de nuevo, el nombre exacto de su tableadapter
{
public System.Data.SqlClient.SqlDataAdapter Adapter2 //el nombre que se les ocurra
{
get
{
this.Adapter.SelectCommand = this.CommandCollection[0];
return this.Adapter;
}
}
}
}

Hasta acá la modificación, si lo estuvieran invocando por ejemplo desde un windows forms, podrían ejecutar lo siguiente (ojo que ahora el código que viene a continuación está adentro de un windows forms que utiliza al tableadapter).

DataSet1TableAdapters.EjemploTableAdapter da = new WinCon.DataSet1TableAdapters.EjemploTableAdapter();
DataSet1 ds = new DataSet1();


public Form1()
{
//atacho los eventos y digo que lo gestionan
// los métodos metodo y metodo2 respectivamente.
da.Adapter2.RowUpdating += metodo; //fijensé que uso la propiedad Adapter2
// que creé adentro del TableAdapter.
da.Adapter2.RowUpdated += metodo2;
InitializeComponent();
}


Espero que a alguien le sea de utilidad.

Hugo Bernachea
http://www.linkedin.com/in/bernachea

viernes, 19 de junio de 2009

Firebird con Visual Studio 2005

********* Consejo Dado "AS IS" "ASI COMO ESTA", sin garantias y bajo la total y absoluta responsabilidad de quien lo aplica, como todos los consejos, tipos y sugerencias dados en este sitio *********

Firebird como base de datos "free" no es tan conocida como otras bases de datos mas populares como MySQL y PostgreSQL, pero lo cierto es que Firebird tiene una serie de características que la hacen muy interesante a la hora de realizar desarrollos de programas "empaquetados".
Una de las características es que esta base puede ser embebida en el producto final, con lo cual no se le instala un servidor al cliente. Además Firebird tiene Stored Procedures, Triggers, Funciones y todas las características que presentan las bases de datos comerciales y que MySQL recién está empezando a adoptar desde su ultima versión. Obviamente Firebird es muy superior a SQL Lite e incluso es superior a las versiones express de SQL Server y su licencia comercial permite utilizarlo incluso en programas comerciales sin restricciones.

La idea de utilizarlo con .NET viene pronto a las manos y por lo tanto voy a describir como hacerlo funcionar en Visual Studio 2005.

Pasos a seguir:
1. Ir a la página de Firebird y descargar el provider para .NET 2.
2. Descargue el Visual Studio 2005 SDK (NO el SDK del framework please) desde el sitio de descargas de Microsoft. Recuerden que el SDK del Visual Studio NO es parte de la instalación, es una descarga adicional.
3. Verifique y en caso de no estar previamente agragado, agregue el provider de firebird para .net 2 (el archivito FirebirdSQL.Data.FirebirdClient.dll) a la Global Assembly Cache (GAC) con gacutil.exe -i FirebirdSQL.Data.FirebirdClient.dll.
4. Ejecute gacutil.exe /l FirebirdSql.Data.FirebirdClient y fíjese los números que indica esta ejecución, particularmente el número de version, el publickeytoken y cultura.
5. Ubique el machine.config y fíjese en los siguientes tags:
Desdpués de configuration ->configSections agregue lo siguiente (todo seguido)

add <section name="firebirdsql.data.firebirdclient" type="System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=SU_NUMERO_DE_VERSION, Culture=neutral, PublicKeyToken=EL_PublicKeyToken_DE_SU_DLL_EN_SU_GAC">

6. En <system.data> -> <dbproviderfactories> agregar
<add name="FirebirdClient Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".Net Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient, Version=ACA_VA_SU_NUMERO_DE_VERSION, Culture=neutral, PublicKeyToken=DE_NUEVO_ACA_VA_SU_PUBLIC_KEY_TOKEN">

7. Abra el archivo FirebirdDDEXProvider.reg y reemplace la variable %Path% con la ruta exacta donde se encuentra la dll del provider, por ejemplo C:\Program Files\FirebirdClient, recuerde de agregar doble barra, por ejemplo C:\\Program Files\\FirebirdClient. Guarde el archivo .reg y con un doble click agregue esa información en el registro.

Si hizo todo de la manera correcta ya tiene disponible la opción para abrir el VS 2005 y usar firebird como cualquier otra base de datos, incluso agregando la conexion en el server explorer.

lunes, 5 de enero de 2009

Haciendo Generadores de Codigo con CodeDom

A los que están interesados en realizar sus propios generadores de código en .NET (C# o VB.NET), les dejo un ejemplo para utilizar Codedom (los imports mínimos son: System.CodeDom y System.CodeDom.Compiler )
Lo bueno de CodeDom es que permite generar código de manera genérica pero de implementación concreta, esto es, podemos hacer generadores de código para cualquier de los lenguajes de .NET (c++, C#, Vb.NEt, etc).

Aquí vá el ejemplo que pueden utilizar y probar, este código genera un string con el código de una clase en C# y en VB, con una propiedad llamada ID y un constructor predeterminado. Ideal para comenzar a probar y experimentar.

Dim ns As CodeNamespace 'definiendo un namespace para nuestra clase

Private Sub GeneraClase
'defino un namespace base
ns = New CodeNamespace("PrimerCodeDom")

'agrego los imports correspondientes
'aca pueden agregar todos los imports necesarios
ns.Imports.Add(New CodeNamespaceImport _
("System"))
ns.Imports.Add(New CodeNamespaceImport _
("System.Diagnostics"))
ns.Imports.Add(New CodeNamespaceImport _
("System.Text"))

'creo la clase en si misma
Dim clase As New CodeTypeDeclaration("Clase_Clientes")
'agrego la clase a la colección de tipos
ns.Types.Add(clase)

'defino un campo privado

Dim campo As New CodeMemberField("integer", "_ID")
campo.Attributes = MemberAttributes.Private

'agrego el miembro privado a la clase

clase.Members.Add(campo)

'defino un campo público

Dim p As New CodeMemberProperty()

' le doy un nombre a la propiedad
' ID en este caso
p.Name = "ID"

' lo hago público
p.Attributes = MemberAttributes.Public
p.Type = New CodeTypeReference("System.Int32") 'es integer
p.HasGet = True
p.HasSet = True 'si fuese false, sería solo lectura

'esto que viene es obligatorio
'tengo que decirle que cosa devuelve el get de la propiedad
p.GetStatements.Add( _
New CodeMethodReturnStatement( _
New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "_ID")))
'esto también es obligatorio
'tengo que decirle como se asigna el valor del set
p.SetStatements.Add(New CodeDom.CodeAssignStatement( _
New CodeFieldReferenceExpression( _
New CodeDom.CodeThisReferenceExpression, "_ID"), _
New CodeDom.CodePropertySetValueReferenceExpression))

'agrego la propiedad a la clase
clase.Members.Add(p)

'defino un constructor público

Dim constructor As New CodeConstructor()
constructor.Attributes = MemberAttributes.Public
clase.Members.Add(constructor)

'defino los providers para los lenguajes en los que voy a generar mi clase
Dim csProvider As New Microsoft.CSharp.CSharpCodeProvider
Dim vbprovider As New VBCodeProvider

'en .net 3.5 este código tira un warning por obsoleto,
'pero igual funciona perfecto.
Dim codigo As ICodeGenerator

codigo = vbprovider.CreateGenerator()
Dim vbCod As String = generaCode(codigo)

codigo = csProvider.CreateGenerator
dim csCod as String = generaCode(codigo)

'en este punto, en las variables vbCod y csCod
'tienen el código de la clase correctamente generada.

End Sub

'metodo complementario
Private Function generaCode(ByVal CodeGenerator As ICodeGenerator) As String

Dim options As New CodeGeneratorOptions()

' defino la identación del código
options.IndentString = Space(3)

' creo un StringWriter
Dim sb As New StringBuilder()
Dim sw As StringWriter = New StringWriter(sb)

' genero
CodeGenerator.GenerateCodeFromNamespace(ns, sw, options)

' devuelvo el string con el código generado
Return sb.ToString()
End Function

Una utilidad interesante podría ser utilizar este código para generar un mapeador de clases contra tablas de una base de datos, para lo cual debemos recorrer las tablas de una base de datos, ver código SQL aquí: http://sqldata.blogspot.com/2009/01/como-obtener-todas-las-tablas-de-una.html y por cada tabla recorrer los campos con el Script SQL listado aquí: http://sqldata.blogspot.com/2009/01/como-obtener-todos-los-campos-de-una.html y aplicar el codigo codedom correspondiente para generar un mapeador de clases contra tablas.
O sea, por cada tabla generar la clase en codedom y por cada campo generar dentro de la clase correspondiente las propiedades que necesitemos.

Con eso tienen lo necesario para generarse un mapeador de clases si se ponen manos a la obra.


Hugo Bernachea

viernes, 26 de diciembre de 2008

Donde están las bases de ejemplo de SQL Server 2008??

Si instalaron SQL Server 2008 y notaron que no se instaló ninguna base de datos de ejemplos, a no desesperar, las mismas se encuentran en el sitio opensource de Microsoft, codeplex, mas exactamente en:

http://www.codeplex.com/MSFTDBProdSamples/Wiki/View.aspx?title=Installing%20Databases&referringTitle=Home

martes, 23 de diciembre de 2008

Utilidades Imprescindibles para .NET

Aquí publico un listado de utilidades, frameworks y otros programas que yo considero imprescindibles para los desarrolladores .NET y espero que ustedes puedan agregar las que crean que faltan en el listado:

1) .NET Reflector: http://www.red-gate.com/products/reflector/
Un clásico. Permite descompilar y analizar ensamblados .NET, analizar las clases constituyentes, ver sus métodos, MSIL.























.

2) Autocode: http://www.devprojects.net/
Gratuito.
Es un add-in para Visual Studio .NET que automatiza tareas repetitivas y permite generar código, refactorizar, ejecutar acciones del IDE o cualquier otro comando. Altamente recomendable, una herramienta imprescindible para .NET.





















3) CodeSmith: http://www.codesmithtools.com/
Otro clásico, templates (plantillas) para generar código en distintos lenguajes y con distintos objetivos. ( C#, Java, VB, PHP, ASP.NET, SQL, etc.).
No es gratis, pero es muy util.

4) .NET Memory Profiler: http://memprofiler.com/
Tampoco es gratis, pero permite determinar y optimizar el uso de la memoria en programas realizados en .NET.

5) QuickCode.NET: http://www.mobzystems.com/
Además de QuickCode, Gratuito, la página tiene un montón de utilidades mas, muy interesantes la mayoría de ellas, recomiendo mirar la página.

6) Snippet Compiler: http://www.sliver.com/dotnet/SnippetCompiler/
Gratuito.

7) FxCop: http://blogs.msdn.com/fxcop/archive/2008/08/19/fxcop-1-36-released.aspx
Gratuito. Otro imprescindible y clásico.
FXCop es una herramienta de análisis de código para .NET desarrollada por GotDotNet. Lee ensamblados (dll o exe) directamente para hacer el análisis.
En la actualidad está migrándose a la MSDN y se está integrando con la versión 2008 del Microsoft Visual Studio .Net (ORCAS), pero se puede usar desde cualquier versión de Visual Studio.

8) NUnit: http://www.nunit.org/index.php
Gratuito. La implementación .NET del Framework de testing de java unit, imprescindible en la arquitectura TDD.

9) NDoc: http://ndoc.sourceforge.net/
Gratuito. Genera documentación para los ensamblados .NET.

10) NAnt: http://nant.sourceforge.net/
Gratuito. Portado del Ant de Java, permite automatizar los procesos de compilación y Builds de los aplicativos.

11) PInvoke.NET add-in: http://www.pinvoke.net/
Permite encontrar y determinar las llamadas a win32 y apis desde código manejado (.Net).

12) Regulator: http://sourceforge.net/projects/regulator/
http://regulator.sourceforge.net
Herramienta de testeo de expresiones regulares, muy bueno.

13) Asp.NET Version Switcher:
http://www.denisbauer.com/NETTools/ASPNETVersionSwitcher.aspx

14) Resharper: http://www.jetbrains.com/resharper/
No solo refactoriza código, es una herramienta multipropósito.

15) NHibernate: http://www.hibernate.org/343.html
Framework de persistencia de datos, heredado del Hibernate de Java, con soporte para múltiples bases de datos. Ya se que existe Linq, pero todavía está verde, en cambio Hibernate ya viene con un camino recorrido y además es una tecnología abierta multiplataforma, multi-base de datos. Además parece que Linq to SQL está moribundo, de modo que yo me sigo quedando con Hibernate, además como también programo algunas cosas en Java, con Hibernate puedo programar exactamente lo mismo en un lenguaje (C#) que en otro (Java).

Hasta aquí la lista, espero que puedan agregar las herramientas que crean conveniente.


Hugo Bernachea
http://www.linkedin.com/in/bernachea
MCSD / MCDBA / MCT

domingo, 26 de octubre de 2008

Nothing y DBNull.Value en Visual Basic.NET

Que diferencia hay entre Nothing y DBNull.value???

Mucha gente está bastante confundida acerca de este tema y no son pocos ciertamente los que lo están. Vamos a tratar de esclarecer en forma rápida y concreta este tema.

La palabra clave Nothing sirve para especificar o asignar que un variable de tipo referencia no está apuntando a nada, no está instanciado objeto alguno para dicha variable.

DBNull.Value en cambio es un objeto que se usa para indicar que un tipo (type) de un campo de base de datos es de valor nulo (Null).

Yo creo que esta común confusión tiene su origen en las versiones anteriores de VB, ya que contaba con un sinnumero medio de especificar estados de variables (nothing, empty, null, ismissing, "", etc).


jueves, 2 de octubre de 2008

Casteo Dinámico de tipos (type)

Estaba haciendo un código con un toque de reflection.
Necesitaba un casteo entre tipos que se iban a resolver solamente en tiempo de ejecución, de modo que el casteo común y corriente no me servía. Después de dar un par de vueltas fuí a los mas simple, la clase Convert y su método ChangeType, tal como aparece a continuación.

string tipo = "System.Int16";
object objeto1 = "345";
object objeto2 = Convert.ChangeType(objeto1, Type.GetType(tipo));
Type t = objeto2.GetType(); // y aca tengo el tipo del system.int16 nuevamente

Comentarios:
objeto.GetType devuelve el tipo de un objeto existente.
gettype(type) devuelve el tipo de un tipo indicado especificamente
y
Type.GetType(String) devuelve el tipo que le indicamos en el string.

domingo, 21 de setiembre de 2008

Generación de Código con MyGeneration

Generadores de Codigo

Un generador de código permite agilizar el desarrollo de aplicaciones, yo lo estoy utilizando con un proyecto pequeño para ver que resultados obtengo.
Hasta ahora he logrado ahorrar tiempo y a la vez programar dentro de todo algo prolijo, es una buena forma de no caer en la típica programación con toda la logica pegada a la interfaz al estilo VB6 cuando necesitas hacer algo rápido. Asi queda algo elegante sin que ello nos involucre horas y horas de programar capas.
La aplicación que utilice para hacer esto se llama MyGeneration esta aplicación permite utilizar distintos templates que escriben código, vos podes armar el tuyo o usar alguno de los que ofrece entre ellos dOOdads y NHibernate, el último es muy conocido en el mundo de java.
Yo opte por probar con dOOdads, que por medio de una jerarquia de herencia te permite crear clases que mapean contra las tablas de tu base de datos para que después puedas usarlas de esta forma:

// Load and Save
Employees emps = new Employees();
if(emps.LoadByPrimaryKey(42))
{
emps.LastName
= "Just Got Married";
emps.Save();
}

// Add a new record
Employees emps = new Employees();
emps.AddNew();
emps.FirstName
= "Mr.";
emps.LastName
= "dOOdad";
emps.Save();



// After save the identity column is already here for me.
int i = emps.EmployeeID;
Les comento a grandes rasgos los pasos que hay que hacer para que salga andando:
1) bajar MyGenerator desde sourcefoge que es donde esta la última version del generador y del template.(acá el link http://sourceforge.net/projects/mygeneration )
2) Una vez instalado el programa necesitaras tener una base de datos bonita y lista para mapear hacia objetos.
3) La arquitectura de oddododos (o como se escriba) tiene los siguientes modulos:
a- un proyecto que tiene las clases bases que van a implementarse luego por el generador de código
b- los procedimientos almacenados que utilizan las clases para guardarse en la base de datos
c- un conjunto de vistas en la base de datos que debes crear para utilizar datos relacionados de forma eficiente.
4) Entonces para que esto ande primero tenemos que agregar a nuestro proyecto el proyecto de arquitectura de dOOdads, el mismo se encuentra en C:\Program Files\MyGeneration\Architectures\dOOdads\CSharp para la version C#.
5) Una vez que elegimos cual es la base de datos a usar tenemos que marcar la clases de la carpeta C:\Program Files\MyGeneration\Architectures\dOOdads\CSharp\MyGeneration.dOOdads\DbAdapters que vamos a usar (ver los prefijos) para que compilen. Para ello la seleccionamos y en el cuadro de propiedades la maracamos para incluirla en el build.

En la imagen muestro las dos clases que abría que cambiar la propiedad "Build Action" para que compile un proyecto con base de datos SQL Server 2000 o 2005.

6) una vez que tenemos el proyecto referenciado, vamos a generar nuestras clases de negocio. Para ello iniciamos mygeneration configuramos la cadena de conexión hacia la base de datos que vamos a mapear y procedemos a buscar en el arbol de la izquierda los templates a usar.

7) para crear las clases de negocios usamos el template dOOdads Business Entity que se encuentra bajo la rama c# de dOOdas. Este template les genera clases abstractas, si quieren las concretas también hay que hacerlo con el mismo método.
La idea de las clases concretas bobas es que ahí metamos el código especifico de nuestras aplicaciones.
Si van a usar vistas para obtener datos relacionados con joins también se generan desde ese apartado.
8) Tambien necesitamos crear los procedimientos almacenados para eso elegimos la base de datos correspondiente en el arbol de template (por ejemplo Microsoft SQL Server) y corremos el template de dOOdad Stored Procedures. Esto escupe un monton de stores por cada tabla que son necesarios para correr las clases generadas por MyGeneration.
Aca esta bueno tocarlos un poco para que hagan lo que nosotros querramos, por ejemplo en mi caso modifique los deletes para que no borren sino que marquen un campo de baja, y toque también el procedimiento que trae todo para que solo traíga aquellos que no estan marcados como borrados.
TIP: si a cada columna le agregan un campo RowVersion de tipo timestamp, el template va a utilizarla para manejar la concurrencia de los updates y puede llegar a generarles una sentencia TSEQUAL que no compila en 2005, no se hagan drama cambienlo por un igual y sale con frítas.
9) Agregamos todo el código generado a nuestra solución de C#
10) Configuramos TransactionMgr para que obtenga una query string válida para nuestro aplicativo en la fúncion private IDbConnection CreateSqlConnection(BusinessEntity entity), donde pueden traerla directamente del app.config o web.config.

Y con eso ya tendríamos andando una elegante capa de datos completa en no mas de 30 minutos.
Cualquier cosa no duden en preguntar... en la página de mygeneration hay un pdf de 6 paginas que dice básicamente lo mismo que acá y esta práctico para ver como usar bien toda la interfaz que te da.
Por ejemplo tiene un generador dinámico de querys muy piola.

Eso es todo por ahora hasta la próxima espero que le sea útil a alguien....

nota original en: http://rodcode.blogspot.com/2007/08/generadores-de-codigo.html

sábado, 30 de agosto de 2008

Conversor de .NET a JAVA - Grasshopper

La empresa MainSoft (http://dev.mainsoft.com/) ha desarrollado una serie de productos, basicamente plugins para Visual Studio.NET, para convertir un aplicativo .NET en un aplicativo JAVA listo para ser instalado en Linux sobre un servidor Apache Tomcat.

Pueden encontrar el plugin listo para ser descargado en la página de MainSoft: http://dev.mainsoft.com/Default.aspx?tabid=177

Realmente este producto permite desarrollar en la herramienta de mayor conocimiento, usando el lenguaje de mayor experiencia y luego todo ese desarrollo migrarlo a Java en Linux con facilidad, incluso para aquellos que poseen escasa experiencia en esas plataformas.

Muy interesante !.

lunes, 14 de julio de 2008

Como manejar los eventos de botones creados dinámicamente en asp.net

Un amigo me consultó hace un par de días acerca de un problema que el estaba teniendo con una página en la que dinámicamente generaba unos botones, les atachaba los eventos click mediante addhandler pero en tiempo de ejecución la página aspx ignoraba olímpicamente dicha codificación.

La codificación era del siguiente estilo:


Dim btnBoton As New Button
btnBoton.Text = "Click en este botón"
Page.Controls.Add(btnBoton)


Una vez que el botón está en la página no hay forma de hacer que responda al evento click.

No podía creer que algo tan sencillo no funcionase, de modo que empecé a buscar en todo internet, aunque me imaginaba que si agregaba un campo oculto y registraba la propiedad correcta todo iba a funcionar.

Entonces, primero hay que registrar un campo oculto en la página.


Page.ClientScript.RegisterHiddenField("BotonOculto", "")


Despues definimos el botón en forma dinámica.


Dim miBoton As New Button
miBoton.Text = "Click en este boton"


Y el secreto agregar desde el lado servidor un attribute al lado cliente que directamente envie el submit de la página mas el botón clickeado


objButton.Attributes.Add("onClick", & _ "document.forms[0].BotonOculto.value='" & _
miBoton.UniqueID & "';document.forms[0].submit();")


Bien drástico y concreto, uso el Dom y envio el submit desde el evento onClick previamente registrado.

Finalmente agrego el control a la coleccion de controles de la página.


Page.Controls.Add(miBoton)


Lo unico que resta es tomar en el postback que genera dicho botón el valor del item correspondiente y listo.

Entonces en el postback:


If Page.IsPostBack Then
If Request.Item("botonOculto").Length > 0 Then
Response.Write("Usted clickeó en el botón " & _
Request.Item("botonOculto") )
End If
End If


Línea mas, línea menos, así es como debiera quedar la cosa.

Y problema resuelto !

martes, 8 de enero de 2008

configurando Web.Config para Web Parts

Recuerden que para trabajar con WebParts deben crear la base aspnetdb por medio del utilitario de línea de comando: aspnet_regsql
Una vez creada dicha base de datos debemos agregar las siguientes líneas en el web.config:






























(En caso de no poder visualizar la imagen clickear sobre la misma, lo cual provocará que se cargue la imagen por completo).

Con todo esto ya debieran funcionar nuestros webs con web parts

miércoles, 28 de noviembre de 2007

martes, 27 de noviembre de 2007

sábado, 24 de noviembre de 2007

Otra buena con Patterns

http://www.designpatternsfor.net/

Patterns en .NET - Listado y ejemplos

En :
http://www.dofactory.com/Patterns/Patterns.aspx

Tenemos un listado de patterns categorizados por creacionales, estructurales y de comportamiento, junto con un ejemplo en C# de cada uno de ellos.

Strategy Pattern

Todos los desarrolladores .NET conocerán la importancia de los patterns de desarrollo para optimizar el modelo de un aplicativo, para facilitar su mantenimiento, para hacer más dinámico y flexible dicho modelo.

Existen unos cuantos artículos al respecto, uno de ellos en la espectacular página de willy Marroquin:

http://www.willydev.net/descargas/WillyDev_FDO_Strategy_Csharp2.0.pdf

domingo, 18 de noviembre de 2007

Todas las cadenas de Conexion !!

Si quieren saber como conectarse a un Servidor de bases de datos y no encuentran la cadena de conexión, pueden ir a la página:

http://www.connectionstrings.com/

En esta página se encuentran todas (o casi todas) las posibilidades de configuración de cadenas de conexión a distintas bases de datos.

martes, 10 de abril de 2007

OpenXML en SQL Server 2000

Pasando multiples registros de datos a SQL Server 2000 por medio de XML y OpenXML
Desde ya que en SQL Server 2005 existe el tipo de datos xml que permite longitudes de datos de hasta 2Gigas. En SQL Server 2000 NO existe este tipo de datos y el varchar es limitado en cuanto a longitud de datos.

SQL Server - Instrucciones Cube y Rollup

Aquí tenemos un pdf para descargar con excelentes ejemplos de cuando y como utilizar las instrucciones Cube y Rollap usando Ansi SQL (compatible con Transact-SQL)
Como siempre, excelente la página de Willy Marroquín.

Hola !

Hola !, Soy román, soy MCSD, experto en tecnologías .NET y en SQL Server.
Este es mi blog sobre acerca de las tecnologías .NET, los lenguajes C# y Visual Basic.NET y también sobre SQL Server y las tecnologías relacionadas.

Acá es donde voy a exponer mi experiencia personal, mis conocimientos y las noticias mas destacadas acerca de .NET y SQL Server desde el punto de vista de los desarrolladores.

Espero que este sea un ámbito de comentarios e intercambios de información entre desarrolladores de habla hispana.

Hola a todos y bienvenidos a mi Blog !!