Experimentando con indices en SQL Server – En vivo

¿Cual es la diferencia de utilizar o no utilizar indices en nuestras tablas? Experimento con unas consultas para ver el rendimiento de utilizarlos y no utilizarlos:

SAT, cfdi 3.3, facturación electrónica, la opinión de un desarrollador de software PARTE I – Adaptación

Esta entrada fue impresa en el número publicado en Marzo 2018 de la revista Talento Empresarial.

Mi experiencia con facturación electrónica viene desde el desarrollo de la plataforma www.facturacenter.com.mx, posterior a ese desarrollo he hecho miles más que van desde servicios web, consultoría a empresas y algunos municipios del país, y lo último la migración de cfdi 3.2 a 3.3 de algunos sistemas.
Tratare de dar mi punto de vista como desarrollador de software, no soy experto en contabilidad ni temas fiscales, yo solo soy un desarrollador de software por lo cual puedo desconocer algunos temas a la perfección. En esta entrada me enfocare en la adaptación de los usuarios a este mecanismo.

¿Por qué facturación electrónica?

Entiendo las ventajas que significan para SAT que los contribuyentes emitan facturas electrónicas, ya que esto da mayor control a todo movimiento que hacen las pequeñas y grandes empresas, y poco a poco quitando el trabajo de los contadores de calculadora, y todo electrónico sin gastar papel, ni renovar los folios y todo el engorro que se hacía hace años. Lo malo del asunto es haber optado por sacar una versión 3.2 con tanta deficiencia la cual quieren tapar con la nueva versión 3.3 (la cual creo que complica todo al contribuyente, ahorita vamos para allá). No sé a quién consulto SAT para realizar la facturación electrónica en cuanto a sus secciones y formatos, catálogos, atributos, complementos etc. Hay características buenas como todo, pero las deficiencias que tenía la versión 3.2 quisieron mejorarlas teniendo un mayor control en lo que captura el contribuyente, cambiándolo todo (o casi todo) a claves, esto asegurando que el emisor no captura discrepancias, todo suena perfecto y como programador lo aplaudo, pero esto debió ser parte de la versión 3.2 no de la 3.3. ¿Qué es lo que pasa ahora con todo el tema de la migración? Que todos los sistemas fueron hechos para la versión 3.2 una versión que fue perfeccionándose y si la comparamos con la versión 3.3 hace un caos en los sistemas y en los usuarios que utilizan dichos sistemas.

CFDI 3.2

Un usuario que estaba acostumbrado: 10,20 quizá 30 o más años a hacer sus facturas con papel se le obliga a realizar facturación electrónica, ya que no fue opcional sino obligatoria al final, esta persona nunca ha utilizado una computadora, meses después el usuario comienza a crear su factura, y de repente le toca un cliente al cual le obliga hacer una addenda, el usuario no tiene ni idea que es una addenda, lo peor aún, el sistema que utiliza el usuario no tiene dicha addenda(si porque cada receptor puede hacer su addenda), el usuario llama a su proveedor de software y le dicen que la addenda estará lista en unos días. Por fin llega el día y el usuario ve que para hacer una factura para ese cliente en particular (ya que si la factura está mal no recibe su pago) debe llenar más datos y cuando por fin logra hacer la factura, se encuentra con una nueva sorpresa, el cliente le dice que la factura debe subirse a una página web la cual validara la addenda, y al subirla el sitio del cliente le dice que su factura no es válida; la persona nuevamente llama a su proveedor de software y se vuelve un ciclo prueba y error hasta que resuelve una problemática que no tenía cuando solo utilizaba papel. Este es un pequeño ejemplo de la problemática que pasó un contribuyente al migrar de papel a facturación electrónica. ¿Sera verdad que con la facturación electrónica se beneficia el contribuyente? O ¿Quién se beneficia realmente? El contribuyente en lugar de beneficiarse ha gastado en un software caro y en más tiempo del que utilizaba para hacer algo que hacía en minutos.

CFDI 3.3

Después de 6 años cuando los contribuyentes por fin llevan una vida más o menos tranquila en cuestión de facturación (a veces falla el pac, se caducaron sus sellos), y sale la súper noticia de la migración a la nueva súper poderosa facturación electrónica 3.3 la cual contiene miles de mejoras, más organizada, lo mejor que le pudo pasar al contribuyente, y arrojan como 20 catálogos los cuales deben ser utilizados ahora en lugar de que el usuario capture lo que siempre capturaba. Ahora para capturar conceptos el SAT obliga a que capture el usuario el producto y una clave que proporciona el bondadoso SAT, y lo dicen como si el usuario solo buscara la clave entre más de 50 mil (un numero absurdo y más adelante veremos porque) y rápidamente le resolviera su vida pero aquí es por lo cual dije con anterioridad, estos catálogos debieron salir en la anterior versión, las personas ya utilizan sistemas donde tienen hasta miles de productos, los contribuyentes viven al día, y ahora para hacer una factura deben ir producto por producto buscando la clave más o menos adecuada (ya que hay ambigüedades) esto en el caso de los conceptos, ah pero si te equivocas el SAT te dará perdón unos meses porque los contribuyentes son unos pecadores por no saber cuál es la clave de sus conceptos. Ahora veamos lo absurdo de este famoso catalogo:

  • Clave 92111704 – Guerra de guerrillas
  • Clave 25151501 – Nave espacial tripulada
  • Clave 11131602 – Semen
  • Clave 92112100 – Guerra nuclear
  • Clave 92112207 – Guerra ambiental
  • Clave 92112403 – Guerra nuclear
  • Clave 92112404 – Guerra basada en el espacio
  • Clave 92111806 – Mercenarios

Estos son unos ejemplos, y es cuando me pregunto ¿En realidad eran necesarios más de 50 mil elementos? Además esto está lleno de huecos, hay bastantes ambigüedades, y otro problema es que ese catálogo debe seguir creciendo a la lógica del SAT, ya que habrá cada vez nuevos productos, creo que si querían absorber todo producto posible se metieron en un problema enorme. Se debió contemplar una categorización menor, no más de 1000 elementos, esto ayudaría bastante al usuario, pero yo casi estoy seguro que este catálogo tiende al fracaso. El simple hecho de evaluar si corresponde lo que capturo el cliente con la clave ya es algo engorroso, así que no dudo que el siguiente año se elimine o se reduzca este catálogo así como el de unidad que también es otra maravilla.

Hablar de facturación electrónica es un tema para más de una entrada, es por ello que me enfoque en la adaptación en estos años, en otras entradas hablare de los monopolios existentes, nomina electrónica, y también del famoso y paradójico complemento de pago.
La facturación electrónica también tiene sus puntos buenos y puede mejorar la forma en como está organizada, lástima que SAT teniendo recaudaciones enormes (2015: 300 mil millones de pesos) no invierta ni el 1% de eso para su departamento de sistemas (siguen utilizando applets, yo amo java, no las applets).
Nos vemos en siguientes entradas.

SAT, cfdi 3.3, facturación electrónica, la opinión de un desarrollador de software PARTE II – Beneficio.

¿Cómo conectarnos a un proyecto en desarrollo en Visual Studio desde otra computadora? .Net

Algunas veces tenemos la necesidad de conectarnos a un proyecto que está en desarrollo, es decir está programándose aun y se encuentra en una solución de visual studio, ya sea para probar una aplicación móvil conectándose al servicio web o para conectarnos desde un celular y ver como se verá un sitio web responsivo.
Los pasos son los siguientes, todos son sobre el equipo que tiene el código fuente:

  • Desactivar el firewall (Importantísimo).
  • Verificar la ip del equipo.
  • Todos los proyectos de visual studio tienen una carpeta oculta llamada .vs dentro de esta carpeta se encuentra una llamada config y dentro un archivo llamado applicationhost.config (quedando así la ruta “.vs/config/applicationhost.config”). Abrimos este archivo con notepad u otro editor de texto.
  • Ahora buscamos nuestro proyecto en el Xml el apartado Sites y debe aparecer algo así:

 <site name="MiProyecto" id="1">
                <application path="/" applicationPool="Clr4IntegratedAppPool">
                    <virtualDirectory path="/" physicalPath="C:\Users\User\Documents\MiProyecto\MiProyecto" />
                </application>
                <bindings>
                    <binding protocol="http" bindingInformation="*:2248:localhost" /><span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
                </bindings>
</site>

  • Ahora agregamos la siguiente línea quedando así (suponiendo que el puerto es el 2248 y la ip 192.168.0.26) :

 <site name="MiProyecto" id="1">
                <application path="/" applicationPool="Clr4IntegratedAppPool">
                    <virtualDirectory path="/" physicalPath="C:\Users\User\Documents\MiProyecto\MiProyecto" />
                </application>
                <bindings>
                    <binding protocol="http" bindingInformation="*:2248:localhost" />
	            <binding protocol="http" bindingInformation="192.168.0.26:2248:*" />
                </bindings>
</site>

  • Por ultimo corremos visual studio como administrador, el proyecto ya podrá ser visto desde otro equipo en la misma red por medio de la ip más el puerto.

Con eso bastara para que puedan conectarse de otro equipo a la maquina que tiene el desarrollo, sin importar que el otro equipo esa movil, mac o pc, e igual podrá debuggearse el código.

Corregir el error: Método ambiguo en Dataset visual studio, dataset corrupto

Hace poco me toco modificar un proyecto que tenía sin modificarlo algunos años, mi sorpresa fue que al modificar el DataSet se destruyó y todos sus métodos, TableAdapters etc me marcaba como si fueran ambiguos o inexistentes. Después de unas horas sufriendo logre corregirlo de la siguiente manera:

  1. Eliminar el archivo .xsc y el .xss.
  2. Excluir él .xsd del proyecto (no eliminarlo, solo excluirlo)
  3. Volver a incluir el .xsd al proyecto (esto regenera el .xsc y el .xss).

Y listo con esos pasos se restablecerá el DataSet.

Un poco de abstracción en la programación no hace daño

Este es un tema muy subjetivo pero el cual es tan importante como el conocer el lenguaje de programación y herramientas de terceros.
La abstracción es un concepto filosófico que comenzó por las reflexiones filosóficas de aquel pensador llamado Aristóteles (dudo que hubiera sido el primero), y se resume como las propiedades y funciones que hacen un objeto (esos griegos ya sabían POO). En palabras simples, la abstracción es aquello que hace que un triángulo no sea un cuadrado, y si un sujeto entiende un triángulo a la perfección y otro sujeto también lo entiende a la perfección deberían ver el concepto de triángulo de la misma forma. Claro esto es yéndonos al extremo de abstracción.
¿Entonces todas estas cosas marihuanas a que nos llevan o para que nos sirven en la programación? Pues sirve prácticamente para trabajar menos.
Los requerimientos son los que definen un problema y para resolver ese problema es para lo que nos pagan, cuando tenemos un par de años trabajando desarrollando software es más fácil identificar los requerimientos parecidos y por lo cual es más fácil aplicar funcionalidades compartidas, en sí, estamos aplicando abstracción funcional al desarrollo, por lo cual trabajaremos menos pero pensaremos más (cuando digo más no hablo de tiempo aplicado sino de complejidad).
Un poco de abstracción no hace daño, un poco de herencia, sobrecarga y rehusó de funcionalidad ayuda a crear más estética en nuestro código, pero como todo, el exceso es malo, el balance de cuanta abstracción utilizar es decisión de uno, y cuando hablo de saber cuánto rehusó de funcionalidad utilizar, hablo por los cambios de requerimientos que a veces van desde una funcionalidad única en solo un módulo la cual nos hace re-codificar mucho.
Como conclusión, la abstracción es algo que se aprende por uno mismo con la experiencia, ni un curso ayudara a tener mejor abstracción, ni gurus, ni evangelistas, lo único que nos hará mejorar el nivel son los distintos problemas nacidos de distintos requerimientos.

Ver – Abstracción en la programación 

¿Cómo crear una función en transact-sql que reciba una cadena con los ids para aplicaros con la función In de sql?

Para esto necesitaremos crear la función mítica Split de sql que tiene años en internet y pongo a continuación (desconozco el autor):

CREATE FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20) = ' ')
RETURNS @Strings TABLE
(
  position int IDENTITY PRIMARY KEY,
  value varchar(8000)
)
AS
BEGIN

DECLARE @index int
SET @index = -1

WHILE (LEN(@text) > 0)
  BEGIN
    SET @index = CHARINDEX(@delimiter , @text)
    IF (@index = 0) AND (LEN(@text) > 0)
      BEGIN
        INSERT INTO @Strings VALUES (@text)
          BREAK
      END
    IF (@index > 1)
      BEGIN
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))
        SET @text = RIGHT(@text, (LEN(@text) - @index))
      END
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index))
    END
  RETURN
END

Una vez con la función Split agregada a nuestra base de datos de la siguiente manera podemos aplicar una cadena que contenga ids y aplicarles alguna modificación a los registros dentro dicha cadena, por ejemplo una procedimiento que modifique un campo(o varios) en común de varios registros recibiendo una cadena con los ids:

CREATE FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20) = ' ')
RETURNS @Strings TABLE
(
  position int IDENTITY PRIMARY KEY,
  value varchar(8000)
)
AS
BEGIN

DECLARE @index int
SET @index = -1

WHILE (LEN(@text) > 0)
  BEGIN
    SET @index = CHARINDEX(@delimiter , @text)
    IF (@index = 0) AND (LEN(@text) > 0)
      BEGIN
        INSERT INTO @Strings VALUES (@text)
          BREAK
      END
    IF (@index > 1)
      BEGIN
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))
        SET @text = RIGHT(@text, (LEN(@text) - @index))
      END
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index))
    END
  RETURN
END

Y así la mandaríamos llamar:


EXEC sp_algo '1,3,5,7,77,65,666','leviathan'

Esto es útil y rápido cuando se desea modificar masivamente una colección de registros (por ejemplo desde un backend con entity framework) los cuales tendrán el mismo valor en uno de sus campos, solo tomar precauciones con SQL INJECTION (es 2017 y si aún existe)

¿Cómo recorrer dinámicamente los atributos de un objeto en C#?

En c# existe una manera fácil para recorrer dinámicamente los atributos de un objeto, de la siguiente manera podemos obtener el valor de un objeto dinámicamente y también el nombre de sus atributos en forma de cadena, para ello haremos uso de la clase PropertyInfo con la cual podemos obtener la estructura de nuestro objeto, abajo comento y pongo un ejemplo simple para entenderlo:

Clase para el ejemplo:


public class Auto
{
            public string Nombre { get; set; }
            public string Marca { get; set; }
            public string Modelo { get; set; }

            public int Año { get; set; }
}

Y para realizar el recorrido de los atributos lo hacemos de la siguiente manera:


Auto oAuto = new Auto() { Nombre = "Mi auto", Marca = "Honda", Modelo = "Civic", Año = 2018 };

PropertyInfo[] properties = typeof(Auto).GetProperties();
foreach (PropertyInfo property in properties)
{
     //así obtenemos el nombre del atributo
     string NombreAtributo=property.Name; 

     //así obtenemos el valor del atributo
     string Valor=property.GetValue(oAuto);
     Console.WriteLine("El atributo "+NombreAtributo+" tiene el valor: "+ Valor);
}

Y el resultado:

El atributo Nombre tiene el valor: Mi auto
El atributo Marca tiene el valor: Honda
El atributo Modelo tiene el valor: Civic
El atributo Año tiene el valor: 2018

Si agregamos nuevos atributos a nuestra clase este algoritmo seguiría recorriendo dinámicamente todas la nuevas propiedades de nuestra clase.

¿Cómo ponerle una contraseña a un pdf en c#?

Para poner un password a un pdf en C# podemos hacer uso de la librería iTextSharp(la cual pueden instalar con nuget, ¿Cómo utilizar nuget?) la cual tiene muchas funcionalidades para el manejo de archivos pdf.
Partiendo de un archivo pdf ya existente con el siguiente código:


 using (var input = new FileStream("C:/archivoOriginal.pdf", FileMode.Open, FileAccess.Read, FileShare.Read))
 using (var output = new FileStream("C:/archivoConContrasena.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    var reader = new PdfReader(input);
                    PdfEncryptor.Encrypt(reader, output, true,"tucontraseña", "tucontraseña", PdfWriter.ALLOW_PRINTING);
                }

¿Cómo realizar un join entre 2 base de datos distintas con entity framework y LINQ? C# #linq

No es bueno para el rendimiento hacer este tipo de consultas ya que las tablas están en bases de datos distintas, pero muchas veces es necesario para el hecho de crear un reporte, o cuando se expande un sistema con nueva tecnología y al final el cliente desea un reporte combinado entre sus sistemas viejos y los nuevos, yo les mostrare una manera de poder lograr un join entre dos bases de datos distintas.
El problema es el siguiente(es hipotético no necesariamente es real solo sirve para el ejemplo), tenemos una base de datos (BD1) con las ventas diarias guardadas en una tabla llamada ventas, se nos pide que sea mostrada la venta y a su lado los datos del domicilio de la tienda, pero nos damos cuenta que no contamos con esos datos, esos datos están en una tabla llamada tienda en una base de datos distinta (BD2), entonces necesitamos hacer un join entre las 2 bases de datos, y para hacerlo debemos tomar a consideración lo siguiente:
Debemos evaluar cual tabla tiene menos registros ya que haremos primero la consulta sobre esa tabla primero y esos datos los tendremos en memoria. En este caso la tabla tienda es la que tiene menos datos (una tienda tiene muchas ventas así que el universo es menor por sentido común). Así que primero vamos por las tiendas de la siguiente forma:

//creamos nuestro contexto de la bd2 ya que ahi esta la tabla tienda
var db2= new entitiesTiendaDB();
//obtenemos las tiendas con una consulta simple de linq
var lstTiendas = from d in db2.tiendas.ToList()
                  select d;

Ahora que a tenemos las tiendas, de la siguiente manera hacemos el join con los datos que ya tenemos en la variable lstTienda:


//creamos el contexto de db1 el cual contiene la tabla ventas
var db = new entitiesVentasDB();

//teniendo un viewmodel llamado VentasViewModel el cual tenga solo los campos que necesitamos creamos la consulta
List<VentasViewModel> lst= from d in db.ventas.ToList()
                          //nuestra tienda se une por el campo codigTienda de lstTiendas y por el mismo campo en
                          //la tabla ventas
                          join t in lstTiendas on d.codigoTienda equals t.codidoTienda into un
                          //esto hace que sea un left join,
                          // si no ponen esto solo les regresara todo como inner join
                          from x in un.DefaultIfEmpty()
                          orderby t.nombreTienda
                     select new VentasViewModel
                      {
                          idTienda = (x!=null) ? x.id : 0, //como hicimos left join podría haber datos nullos y debemos evaluar
                          nombreTienda =(x!=null) ? x.nombre : "",
                          domicilioTienda =(x!=null) ? x.domicilio : "", //asi obtenemos el domicilio
                          codigo = (x!=null )? x.codigoTienda : "",
                          total= d.total //este viene en ventas así que accedo con d
                          subtotal=d.subtotal //igual que arriba

                      };

Y así se hace la magia. Dudas en los comentarios.

¿Cómo convertir una cadena XML a Objeto en c#? deserializar

Existen varias formas de llenar un objeto por medio de valores incrustados en XML(deserialización) y esta que planteo a continuación es la forma más comprensible de hacerlo.
Teniendo el siguiente texto de xml:


<padre>
  <hijo>
    <id>18</id>
    <valor>CFE7785</valor>
    <entero>1</entero>
  </hijo>
<padre>

Primero tenemos que hacer un conjunto de clases las cuales nos ayudaran a guardar los valores:

    [XmlRoot("padre")]
    public class padre
    {
        [XmlElement("hijo")]
        public List lstHijos{ get; set; }
    }

    public class hijo
    {
        [XmlElement("id")]
        public int id { get; set; }
        [XmlElement("valor")]
        public string valor { get; set; }

        [XmlElement("entero")]
        public int entero { get; set; }

    }

Y ahora el proceso para la magia:


string xml= "<padre> <hijo> <id>18</id> <valor>CFE7785</valor> <entero>1</entero> </hijo> <padre>"

XmlSerializer serializer = new XmlSerializer(typeof(padre));
using (TextReader reader = new StringReader(xml))
{
        //de esta manera se deserializa
        padre result = (padre)serializer.Deserialize(reader);
}