Jugando con DataTables

Hace unos días veíamos una forma de trabajar con una relación m:n usando LINQ. En esta ocasión vamos a ver otra posibilidad y no voy a poner código, que ando mal de tiempo, así que a ver si consigo explicarme bien.

Supongamos que tengo dos tablas, Series y Personajes. Entre ellas hay una relación n:m (una serie tiene varios personajes, un personaje puede salir en varias series). La tabla que nos permite esta relación digamos que se llama PersonajesDeSerie y que sólo tiene dos campos: IdSerie e IdPersonaje. Por otra parte, en el formulario de personajes, que es donde podemos añadir las series donde aparece el mismo, queremos mostrar el título de la serie y el año de producción (podían ser más cosas, pero tampoco es plan de complicar el ejemplo). Para facilitar las cosas, nos creamos una vista en la base de datos que metemos como DataTable en el DataSet de Personajes. Es decir, tengo tres DataTable: Personajes, PersonajesDeSerie y vMisSeries, ésta última con los campos IdPersonaje, IdSerie, Titulo y Año. En mi caso, metidos en el mismo DataSet por comodidad.

Sigue leyendo

Número de cifras de un número

Comentando anécdotas de clase el otro día me acordé de un problema chorra de programación, de esos para que la gente se acostumbre a usar bucles, variables y tal: invertir el orden de las cifras de un número dado (por ejemplo, convertir el 768 en el 867). Lo primero era conocer el número de cifras del número dado. La solución dada fue jugar con sucesivas divisiones enteras y el resto que daban. Yo llamé al profesor y le dije y, ¿no es más simple tomar la parte entera del logaritmo decimal del número dado y sumarle 1? El profesor lo pensó unos momentos y me contestó ¿y cómo se lo explico a ellos?, señalando a mis compañeros. Y tenía razón, porque ahí había gente de ciencias y de letras y alguno que no había terminado bachillerato. Seguro que se pone a hablar de logaritmos y a más de uno le da un patatús.

Por otra parte, sigo pensando que mi forma es la más simple y elegante.

Odio programar

Lo que pasa es que me gusta programar un poquito más de lo que lo odio. En el fondo es divertido resolver problemas, es bonito buscar una solución elegante, es satisfactorio encontrar esa solución…

Luego compilas y se acaba la satisfacción y empieza el odio. La solución es casi correcta, pero da pequeños fallos; no he contemplado todos los posibles errores; tengo algún fallo estúpido…

Ains… pero en el fondo, es divertido. Frustrantemente divertido. Curiosa situación.

Un ListBox y una relación n:m

Supongamos que tenemos una relación n:m facilita. Por ejemplo, series y los géneros de estas series. Digamos que tengo mi tabla de series con su clave primaria IdSeries, mi tabla de géneros con su clave IdGenero y la otra que tiene únicamente los campos IdSerie e IdGenero para hacer la relación. Digamos también que quiero mostrar los géneros de cada serie en un ListBox, que llamaremos lstGeneros. Y digamos, de paso, que quiero usar ese ListBox no sólo para mostrar los géneros de la serie, sino también para seleccionarlos en altas y modificaciones. Uhm, ya la cosa se complica.

Vayamos por partes: visualización. Esto es lo más fácil y hay opciones para todos los gustos. Por ejemplo, podría generar una vista en la base de datos que me englobase las tablas de género y «géneros de series» y montar un dataset tipado con la tabla de series, la vista y la relación entre ambas. De ahí a montar un maestro-detalle de tutorial, sólo que con un listbox en lugar de un datagridview, sólo hay un paso.

Sigue leyendo

Depurando

Estoy terminando una aplicacioncita para el curro. Lo de terminando es, más bien, pretencioso. Digamos que está alcanzando un «nivel operativo mínimo», que diría Ratchet: altas, bajas y modificaciones. Faltan las consultas y, sobre todo, que imprima. Pero, por lo pronto, da para ir pasando datos, que sin datos pocas consultas y pocos informes van a sacar. Así que ya tengo todo juntito y compila y… no funciona, claro. No funciona bien, vamos: no se bloquean las visitas cuando estoy dando de alta o modificando un cliente, me salta el error de validación de datos al pulsar el botón «Nuevo», la búsqueda rápida hace lo que quiere…

Así que estoy depurando el código. Revisa línea por línea, ejecuta línea a línea. Cambia de sitio alguna línea, revisa la inicialización de esta variable, rastrea de dónde sale esta reacción cruzada…

Y son sólo un puñado de líneas, dos o tres mil, más las que haya generado automáticamente VB. Hacer esto en un proyecto grande tiene que ser un infierno infernal.

En fin, menos mal que funciona y lo que falla son detallitos.

¿Qué camión?

Llevo ya un par de días (si las incidencias con el programa de las tiendas me deja) programando la aplicacioncita para fábrica, empezando por generar los datasets, una vez dejado de lado LINQ to SQL, y las clases de acceso a datos correspondientes. Me encuentro ahora con que tengo que almacenar el valor máximo de la columna timestamp de ésta o aquella tabla para usarlo al actualizar el dataset, tal y como conté (creo) antes.

He estado toda la mañana pensando dónde meter el dichoso array de Bytes que guarda el valor del timestamp: ¿en la clase de acceso a datos? ¿Cómo Static? ¿Shared? ¿En el formulario? ¿Otras (por favor, indique…)?

Después de perder bastante tiempo con esto, me paro, respiro hondo, miro el explorador de soluciones… y se me queda cara de imbécil. Y me digo:

«Niño, ¿sabes lo que estás viendo? Un dataset tipado. ¿Sabes quién lo ha hecho? Tú. ¿Sabes que puedes añadir código personalizado al dataset tipado? Eso lo tienes que saber, es básico. Lo sabes, ¿verdad? ¿VERDAD? Pues entonces, ¿qué coño has estado haciendo toda la mañana, animal de bellota?»

Diez minutos después tengo en la datatable correspondiente una nueva propiedad para el timestamp y todo funcionando.

A veces uno se obceca, o se distrae, y no ve lo evidente, lo simple o, directamente, el toro o el camión que tiene delante de sus narices.

Jugando con valores timestamp

Tengo abandonado el blog. Ambos blogs, de hecho. El arranque tras las (cortas) vacaciones veraniegas está siendo lento. A esto hay que añadir que, en el curro, lo único que he hecho desde que he vuelto es trabajo administrativo. Ahora me toca volver con CNC (Control Numérico Computerizado) porque hay que retocar el armario para la nueva serie. Entre medias, espero sacar tiempo para terminar una aplicación a la que me queda depurarla y empezar una nueva que llevo preparando (la parte teórica y la documentación previa) desde principios del verano.

Para esta segunda conseguí sacar un ratito la semana pasada para probar el uso de marcas de tiempo y de versión para controlar la modificación de registros en la base de datos, con el fin de controlar más fácilmente los problemas de concurrencia. Tras probar varias opciones y posibilidades, lo último ha sido trabajar con el tipo de datos TIMESTAMP de SQL. No tenía pensado sacar ninguna entrada de estas pruebas pero, en fin, así parece que el blog no está abandonado y quizás a alguien le resulte útil.

Sigue leyendo

A vueltas con el TableAdapterManager

Llevo algo más de una semana programando en Visual Basic 2008, ya que, de momento, no hay nada que hacer en CNC. Por como es la aplicación y porque no quiero complicarme la vida (si quisiera, no usaría VB) he tirado de TableAdapterManager en un par de ocasiones. En una, igual que comenté en la entrada anterior dedicada a este componente, dejaba que él abriera y cerrara la conexión. Sin embargo, en la segunda tenía otros accesos a la base de datos, justo antes y justo después a la operación de UpdateAll del TableAdapterManager. En este caso, me venía mejor pararle al «bicho» la conexión ya abierta y que me la dejara abierta una vez terminara. Es imposible, intenta volver a abrir la conexión y se produce el error.

Sigue leyendo

Hay días así

Tengo un problema persistente y puñetero en una aplicación que estoy haciendo en el trabajo. La aplicación es muy simple. Gestiona una base de datos de clientes (tiendas) y las visitas de nuestros comerciales. Ambas tablas, clientes y visitas, se muestran en el mismo formulario, en forma de maestro-detalle, con las visitas en un DataGridView. Vamos, de tutorial de acceso a datos.

El problema es el siguiente: si cancelo una modificación o alta de una visita, se me selecciona el último cliente. Esto se produce si cancelo la operación sin hacer nada o si un control DateTimePicker que tiene la sección de visitas tiene el foco. Si he cambiado a cualquier otro control o bien he modificado/introducido algún dato, al cancelar el alta o modificación se me queda seleccionado el cliente actual.

Ejecutando paso a paso la aplicación no se produce el fallo.

Después de un día rompiéndome la cabeza con ello, he decidido dejarlo de momento. Todavía me quedan otro par de tablas por gestionar en el formulario (productos nuestros en exposición y consumo anual) y es posible que se reproduzca el problema y me dé pistas de por qué ocurre.

Por una parte me gusta programar. Lo encuentro divertido y estimulante. Por otra, me alegro de no dedicarme profesionalmente a esto.

Impedir el cambiar de pestaña en un TabControl

Tengo la costumbre, inculcada por un profesor, de que, en una aplicación con acceso a datos, cuando se ven los datos no se pueden modificar y cuando estamos modificándolos (altas, edición) sólo podemos modificarlos (nada de abrir otra ventana, nada de cambiar de registro…). Estoy haciendo ahora una aplicacioncilla para el trabajo donde he preferido usar un único formulario que muestra los datos en distintas pestañas de un TabControl. De momento, clientes en una pestaña y las visitas de nuestros comerciales a esos clientes en otra pestaña (el resto, con calma). Así pues, y aplicando la filosofía antes mencionada (que se resumen en «el usuario es un manazas»), la idea es que el usuario no pueda cambiar de pestaña si está añadiendo o modificando un cliente o una visita.

En un principio pensé en hacerlo controlando el evento SelectedIndexChanged, pero no queda bien: se produce un molesto parpadeo cuando cambiamos de pestaña y el programa nos vuelve a mandar a la que estábamos. Así que me puse a revisar otros eventos que pudieran servir y encontré Selecting. De la referencia de Visual Studio:

«Se produce antes de que se seleccione una ficha, permitiendo que un controlador cancele el cambio de ficha.»

Efectivamente, sólo hay que indicar un e.Cancel = True para impedir el cambio de pestaña. En mi caso, si no estoy en modo «Ver Datos», impido este cambio.

En fin, por lo menos he sacado algo útil en el día de hoy. Estoy tan espeso que casi todo el día llevo arreglando destrozos que yo mismo he hecho en partes que ya funcionaban.