Null.La historia interminable(1/3)

Esta mañana y después de ver esta entrada en el foro de c# Obtener los registros de una tabla como objetos y guardarlos en una lista y más concretamente estas líneas de código.

   1: object fechaNacim = reader["FechaNacim"];

   2: FechaNacimiento = fechaNacim == DBNull.Value ? null : (DateTime)fechaNacim;

Me han llegado a la cabeza recuerdos del pasado, mucho antes de la existencia de .Net. Os acordáis de ese error típico de las aplicaciones vb “error 91 object variable or with block variable not set”. Y después muerte. Pues ha llovido, pero lo seguimos teniendo presente en nuestras vidas.

Después de citar al viejo vb donde esto se solucionaba con esto

   1: if isnull(ADODC.Recordset.Fields("Cod_Localidad")) then

   2: end if

avanzamos en el tiempo y nos encontramos en la misma o parecida situación un null de la bb.dd nos ocasiona y no pocos problemas.

Si nos situamos en el año 2002 aparece un nuevo señor para solucionarnos el problema DBNull.Value, que pasada. Ya no aparece el error 91 pero si FormatException.

   1: var ValorBd = System.DBNull.Value;

   2: int Valor = int.Parse(ValorBd.ToString())

Y también  SqlNullValueException.

   1: using (SqlConnection cn = new SqlConnection(@"<Cadena de Conexion>"))

   2: {

   3:        cn.Open();

   4:        SqlCommand cmd = new SqlCommand("SELECT CAST(NULL AS INT)",cn);

   5:        SqlDataReader reader = cmd.ExecuteReader();

   6:        while(reader.Read())

   7:        {                    

   8:            int Valor = reader.GetInt32(0);

   9:        }

  10: }

y en vez de tener un premio que era lo que se conseguía antes de .Net obtenemos dos.

Bueno como una de nuestras virtudes es la paciencia  esperamos a 2005 y aparece una de las maravillas del Framework 2.0 System.Nullable<T> o para quien más le guste “?” detrás del tipo, parece que el problema está solucionado, pero no,  simplemente con profundizar un poco nos damos cuenta que las clases del namespace System.Data se han quedado igual y es por eso por lo que esta mañana para leer un null  nos encontramos con las primeras líneas de código de este post.

Seguimos avanzando años y vemos que ese problema parece que se va a convertir en un mal menor con la aparición de Entity Framework y la realidad que así es, pero sigue sin ser perfecto.

Si reflexionamos han pasado por lo menos para mí 20 años y seguimos pensado en Null.

Bueno he de reconocer que desde 2005 yo deje de pensar en el y eso es material para el próximo post o mejor dicho un capitulo más de esta historia.

Próximos capítulos.

Como puedo vivir mejor con Null sino utilizo Entity Framework.

Que le falta a EF desde mi punto de vista para de una vez olvidarnos del Null.

Como una de las cosas que más me gusta es el debate vamos a empezar con un aperitivo. ¿Debería string tener un tipo Nullable o lo que es lo mismo declarar este como “?string” ?

Espero que os haya gustado y sobre todo espero vuestra reflexión acerca de la pregunta.

Utilizando razor para generar un csv

En muchos de nuestros desarrollos nos solicitan la funcionalidad de exportar nuestros datos a diferentes formatos y hoy me ha tocado exportar a csv.

Lo lógico, es que lo hubiese hecho de la forma tradicional simple y sencillo defino un StringWriter y un foreach hasta que acabe,pero los años me están haciendo despertar la imaginación,con lo cual he pensado en hacerlo de otra formaSonrisa.

¿Cómo?.Voy a utilizar una vista que se encargue de generar el csv.

Manos a la obra.

Partimos para el ejemplo de un modelo sencillo una factura con las siguientes propiedades Número,Fecha e Importe.

using System;
using System.Collections.Generic;
using System.Linq;


namespace MvcApplication15.Models
{
    public class Factura
    {
        public int Id { get; set; }
        public DateTime FechaFactura { get; set; }
        public Decimal Importe { get; set; }
    }
}

Lógicamente el segundo paso es crear un controlador y un método dentro de él que nos permita solicitar el csv.

Que tengo que hacer, pues retornar un FileContentResult con MimeType “text/csv”.

public ActionResult GetCsv()
{
    //Generamos RazorViewEngine
    var razorView = new RazorViewEngine();
    var viewEngineResult = razorView
             .FindPartialView(ControllerContext, "_GetCsv", false);

    //Creamos la vista y pasamos el modelo
    var modelo = new List<Factura>()
    {
        new Factura(){Id=1,
                      FechaFactura = DateTime.Now.Date,
                      Importe = 1000},

        new Factura(){Id=1,
                      FechaFactura = DateTime.Now.AddDays(1).Date,
                      Importe = 2000}
    };
    var vista = View(viewEngineResult.View, modelo);

    //Renderizamos la vista
    using (StringWriter sw = new StringWriter())
    {
        var viewContext = new ViewContext(
            ControllerContext, 
            vista.View, 
            vista.ViewData, 
            vista.TempData, sw);
        
        vista.View.Render(viewContext, sw);
        
        var result = Encoding.UTF8.GetBytes(sw.ToString());
        
        viewEngineResult.ViewEngine
            .ReleaseView(ControllerContext, vista.View);
        
        return File(result, "text/csv", "facturas.csv");
    }
            

}

y por último tenemos que definir nuestra vista y solicitar nuestro archivo desde el explorador.

@model IEnumerable<MvcApplication15.Models.Factura>
@{
<text>Numero;Fecha;Importe</text>
}
@foreach (var item in Model)
{
<text>@item.Id;@string.Format("{0:dd/MM/yyyy}", item.FechaFactura);
      @string.Format("{0:###,###,##0.00}", item.Importe)</text>    
}
Nota: todo el texto que que se escribe dentro de las etiquetas <text> 
debe de estar en una sola línea.

Conclusiones.

Pues sencillo que MVC nos deja hacer escapar nuestra imaginación hasta límites insospechables, gracias a ser un framework abierto crece y crece o lo podemos hacer crecer Sonrisa.

Espero que os guste y sea de utilidad.

Mis Agradecimientos

HolaSonrisa, lo normal en estos casos es presentarse con esas cosas bonitas que a todos nos dejan estupendamente frente a los demás,pero a parte de eso, que no dudéis, que lo voy a hacer intentaré con esta presentación escribir algo que empiece a ser útil.

Bueno mis agradecimientos.

Jo a quien, pues primero al que te autoriza a escribir en este magnifico sitio Rodrigro Corral, Muchísimas gracias Rodrigo.

Lluis Franco, me es imposible poner todos tus links porque al final va a parecer que estás escribiendo tú, pero bueno todos te conocen y cito este porque si alguien entra a mi blog que  no se pierda esa magnifica serie que estás escribiendo sobre Parallel Series y de paso alguien podrá leer ese Maestro de Maestros Guiño. Muchísimas gracias Lluis.

Bueno esto sería interminable pero quiero citar a personas con las que en twitter comparto risas y buenos momentos @Jtorrecilla,Eduard Tomas(@eiximenis),Luis siempre estás programando y haciendo cenas:), todos ellos tienen como maestros que son, no es que yo me considere, blog’s en geeks. 

Bueno y la verdad que no me puedo olvidar de la comunidad, a todos los que me aguantáis diariamente en los foros de msdn y más concretamente en el foro de c# donde gracias a Leandro soy administrador. Leandro gracias.

No me podía olvidar de dos personas con las que comparto muchas horas y que  siempre me han alentando a escribir. Escribe, escribe…  Luis Y Ramirez y mi amigo del pajarito Nicoloco.

La verdad que soy un pelota, pero llevo una hora buscando todas las url’s para hacer publicidad con lo cual señores estámos en Marzo así que quiero caramelos por semana santa porque «jamón del norte» no me mandanSonrisa.

Sabía yo que alguien me dejaba en el tintero, esa persona que actúa como tu padre y te dice, céntrate, constancia ,etc . no sabéis quien es? mi gran amigo Salvador Ramos.

Y ahora toca contar un poco de mi historia durante un montón de años estoy ligado al desarrollo de aplicaciones empresariales, de esas que no tienen una entidad, ni dos, ni tres ,sino 500 o más y lo lógico es que tengas que pensarlas de forma muy detallada y examinando hasta el último ;.

Es por eso que hace tiempo leí este post Preventing SQL Injection with the Entity Framework and Data Services y como no me puse a probar y a jugar un poco con esa realidad.

Voy a realizar las pruebas que hice, Aunque os las voy a pasar con Entity Framewoek 4.3.1 o como se llame en el futuro, eso si  CodeFirst, me gusta Sonrisa

1. Vamos a definir un modelo sencillo una entidad y no 500

public class Entidad
    {
        public int Id { get; set; }        
        public string Nombre { get; set; }
    }

    public class Context : DbContext
    {
        

        public DbSet<Entidad> Entidad {get;set;}
            
        
    }

Vamos con la primera prueba

 using (Context ct = new Context())
            {

                var resultado = ct.Entidad.Where(c => c.Nombre == "Hola");
                foreach (var entidad in resultado)
                {

                }
                
            }

El resultado es el esperado me da la impresión que si es vulnerable no esta presente sp_executesql y genera una cadena Demonio.

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Nombre] AS [Nombre]
FROM [dbo].[Entidads] AS [Extent1]
WHERE N'Hola' = [Extent1].[Nombre]

 

bueno pues vamos a intentar que por lo menos a nadie se le ocurra escribir variable.ToString() , creo que es fácil educar al equipo Sonrisa.

Con lo cual vamos a ejecutar la siguiente prueba

 

var variable = "Hola";           
using (Context ct = new Context())
{

        var resultado = ct.Entidad.Where(c => c.Nombre == variable.ToString());
         foreach (var entidad in resultado)
         {

          }
                
 }

Y cual fue mi gran sorpresa, pues sencillo una enorme satisfacción al encontrarme con una exceptión del tipo NotSupportedException con el mensaje “LINQ to Entities no reconoce el método ‘System.String ToString()’ del método, y este método no se puede traducir en una expresión de almacén”.

Y eso , por que? Pues buscando pronto me encontré con esto Asignar método CLR a función canónica y que suerte ToString() no está soportado.Me di cuenta que lo que decía el post era verdad. Estas funciones están en el namespace System.Data.Objects.SqlClient y concretamente expuestas como métodos estáticos de la clase SqlFunction.

Espero que os haya gustado, hasta el próximo.