Year: 2014

Error: Concurrent number of AOS for this application exceeds the licensed number

Otro error recurrente al mover o copiar entornos o bases de datos es referente al número máximo de AOS que podemos ejecutar en una misma instalación por cuestiones de licencia. Esto ocurre en diferentes versiones y revisiones pero en mi caso me lo estoy encontrando sobre todo en AX 2012: Object Server 01:  Concurrent number of AOS' for this application exceeds the licensed number AX 2012 Para solucionarlo, podemos ejecutar esta sentencia en la base de datos que hemos copiado: [cc]UPDATE dbo.SysServerSessions SET Status = 0 WHERE Status = 1;[/cc] Esto liberará las sesiones que hayan quedado almacenadas en la base de datos antes de copiarla, permitiendo conectarle un AOS diferente, lo que es totalmente válido para una licencia normal y bastante típico al copiar bases de datos de producción para refrescar entornos de pruebas o desarrollo. NOTA: Ejecutar sentencias SQL directamente sobre la base de datos siempre supone un riesgo. Ejecutar con precaución y en entornos de testeo.
Read More »

Microsoft Dynamics AX 2012 R3 CU8 Demo VM V1

Microsoft Dynamics AX 2012 R3 Ya se ha publicado la máquina virtual demo de la también recién publicada Microsoft Dynamics AX 2012 R3 CU8. Esta máquina virtual viene, como de costumbre, actualizada con las últimas versiones de todo el software y con datos de prueba de las nuevas funcionalidades: Se puede descargar de PartnerSource y CustomerSource: Recordar la posibilidad que tenemos desde la revisión R3 de desplegar estas máquinas virtuales directamente en Azure desde , como ya comenté hace un tiempo :)
Read More »

En busca de la tabla perdida… herencia de tablas en AX 2012

Si alguien ha creado o mantiene un desarrollo que acceda directamente a la base de datos de Microsoft Dynamics AX 2012 (por ejemplo, algún sistema externo de Business Intelligence), se habrá encontrado con el fenómeno de la "tabla fantasma". Hay muchos casos, pero analicemos por ejemplo la tabla OMOperationUnit. Esta tabla existe en el AOT, podemos explorarla desde Dynamics AX y ver los datos que contiene, por lo que esos datos deben estar almacenados en alguna parte. Sin embargo la tabla no existe en la base de datos SQL Server subyacente. Entonces, ¿Dónde están los datos? En primer lugar hay que fijarse que este fenómeno sucede siempre en tablas heredadas o que soportan herencia, por ejemplo: Tablas heredadas en Microsoft Dynamics AX 2012 Como la tabla existe y almacena datos en el AOT, es obvio que la tabla debe existir en la base de datos. Una buena herramienta de la que disponemos en X++ es la función getSQLStatement que podemos usar en variables de tipo buffer o en consultas, de esta forma:
static void Job43(Args _args)
{
    OMOperatingUnit tabla;
 
    select generateOnly tabla;
 
    info(tabla.getSQLStatement());
}
Esta función nos devuelve el SQL que se enviará a la base de datos para obtener los datos que se requieren desde X++. Aquí tenemos la explicación al problema de la tabla fantasma: Consulta SQL de tablas heredadas en Microsoft Dynamics AX 2012 Si analizamos bien el SQL obtenido, incluso si lo probamos directamente contra la base de datos SQL Server, descubrimos la estructura interna que el AOT ha desarrollado en la base de datos para almacenar los datos de las tablas heredadas: Consulta SQL de tablas heredadas en Microsoft Dynamics AX 2012 En este caso, la tabla heredada obtiene los datos de tablas totalmente diferentes mediante algunos filtros. Dependiendo del tipo de tabla heredada, las tablas físicas pueden tener otra forma, pero en cualquier caso de esta forma obtenemos una consulta válida que podemos utilizar para acceder a los datos desde un sistema externo, o podemos crear una vista con esa consulta para simular la existencia de la tabla, si fuera necesario.
Read More »

Cumulative Update 8 para Microsoft Dynamics AX 2012 R3

Microsoft Dynamics Aunque se ha hecho esperar un poco más de lo acostumbrado, ya tenemos disponible la siguiente actualización acumulativa para Microsoft Dynamics AX 2012 R3, que será la CU8 (6.3.1000.309) siguiendo el orden de numeración que se estableció en la última CU7 (Esta es la primera CU para R3, no hay CU1, 2, etc. para esta versión). Como de costumbre desde hace algunas revisiones, además de todos los hotfixes publicados con anterioridad de manera acumulativa, incluye algunos cambios funcionales y, en este caso, escasos cambios a nivel técnico. El más importante a tener en cuenta es que a partir de la versión AX 2012 R3 CU8 la versión de Visual Studio necesaria para trabajar con AX  será Visual Studio 2013 de manera obligatoria. Sera necesario desinstalar el antiguo Visual Studio 2010 (cuyo soporte oficial termina el próximo mes de Julio) ya que no está soportada la instalación de ambas versiones en el mismo equipo. Sin embargo, para el diseño y visualización de informes necesitaremos las Data Tools (antiguo BIDS) de Microsoft SQL Server 2012. Más información sobre todos estos temas en los siguientes enlaces: Descarga en: Esta actualización también incluye mejoras respecto a LCS, y está disponible para instalación mediante el módulo Updates de Lifecycle Services, pero sobre LCS hablaremos en el próximo post ;)  
Read More »

Errores de caché tras migración a Microsoft Dynamics AX 2012 R3

Este es uno de esos post que escribo para mi propia referencia. Tras una reciente migración de 2012 RTM a 2012 R3 hemos estado experimentando unos errores bastante extraños. Los objetos compilaban perfectamente tanto en X++ como en CIL, no estaban modificados por lo que ejecutaban lógica estándar, y sin embargo estaban fallando a un nivel de profundidad en el core estándar que hacia peligrar la salud mental de quien intentaba depurarlo. Mediante esta depuración todo parecía apuntar a un problema de caché al deserializar ciertos objetos, no funcionaron las funciones típicas de limpieza de cachés disponibles en el cliente de desarrollo ni los datos de uso, así que investigando di con un post de la comunidad Dynamics que ofrecía una solución tan sencilla como efectiva: la ejecución del siguiente Job:
static void ResetClientCacheGuid(Args _args)
{
    #AiF
    SysSQMSettings settings;
 
    ttsbegin;
 
    update_recordset settings
        setting GlobalGUID = str2Guid(#EmptyGuidString);
 
    ttscommit;
}
Gracias a Ali Raza Zaidi, compañero MVP, por el código que funciona perfectamente.
Read More »
Portada del libro Desarrollo en Microsoft Dynamics AX 2012

Libro: Desarrollo en Microsoft Dynamics AX 2012

Estoy muy ilusionado de poder anunciar el proyecto en el que he estado trabajando este último año, causa principal (probablemente no la única) de que haya publicado con menor intensidad en el blog. Se puede adquirir ya mismo el libro "Desarrollo en Microsoft Dynamics AX 2012", publicado por Krasis Press en su "colección de las frutas" :)

Es el único libro del mercado escrito en castellano sobre desarrollo en Dynamics AX en general, y también lógicamente sobre desarrollo en AX 2012. Además, está actualizado con las novedades de la reciente versión AX 2012 R3.

Está escrito de manera didáctica y progresiva, de manera que sirve tanto como manual para aprender a desarrollar en Microsoft Dynamics AX, así como de manual de consulta o material de referencia para desarrolladores con experiencia, para buscar algún aspecto concreto utilizando el índice (muy detallado) y el glosario de términos. El índice, el glosario y los dos primeros capítulos se pueden descargar GRATIS desde la página de compra, además del prólogo que debo agradecer a Salina Marí, de Microsoft.

PORTADA Desarrollo en Microsoft Dynamics AX 2012

Se puede adquirir en versión impresa (gastos de envío incluidos en el precio!!) y también en formato electrónico para leer en cualquier dispositivo, en cuyo caso se descarga inmediatamente tras la compra. Esta última quizás sea la mejor opción para los amigos de latinoamérica, que me consta son muchos y fieles :D

Se puede comprar en los siguientes enlaces:

Si lo has comprado, estaré muy agradecido de recibir cualquier comentario al respecto por cualquiera de las vías habituales (twitter, linkedin, comentarios del blog, etc.) o bien en portales específicos como:

Si tienes dudas sobre el contenido descarga GRATIS los primeros capítulos en la página de compra.  Recuerda, es el único libro sobre desarrollo en AX 2012 en español. Espero sinceramente que puedas adquirirlo, que el contenido te permita mejorar y aprender, y que después me cuentes tu opinión para seguir mejorando.

Read More »

Microsoft Dynamics AX 2012, tablas TempDB y Formularios

En versiones anteriores disponíamos de diferentes técnicas (no muy intuitivas) para utilizar tablas temporales en formularios. Estas mismas técnicas pueden utilizarse en AX 2012, donde además, tenemos diferentes tipos de estas tablas. En particular me interesan las tablas de tipo TempDB porque son las que mejor rendimiento obtienen, al estar gestionadas por el motor de Microsoft SQL Server. Este es uno de esos post que escribo para tener localizada la información y volver a ella en futuras referencias :) Una versión muy sencilla de uso de estas tablas es similar a como lo hacíamos en la versión 2009, sustituyendo la función setTmpData por linkPhysicalTableInstance. De esta forma, creamos un formulario, añadimos la tabla temporal al origen de datos, etc. y finalmente el método init del formulario queda de esta forma:
public void init()
{
    // ...
 
    super();
 
    JAEETablaTmp.linkPhysicalTableInstance(JAEETablaTmp::createRecords(desde, hasta));
}
El origen de datos se enlaza con un buffer de la tabla temporal devuelto por la función que inserta los datos. De forma que esos datos que devuelve la función son los que se muestran en el formulario. Una forma más avanzada de hacerlo, que ofrece más flexibilidad para actualizar los datos posteriormente, es usar una variable de la tabla temporal,que posteriormente podamos manipular. En este caso hay que tener en cuenta el ámbito (scope) de existencia de los datos en la tabla temporal, para lo cual debemos pasar la misma variable a las funciones que manipulen los datos, para no perderlos.
public class FormRun extends ObjectRun
{
    JAEETablaTmp   tmpTable;
}
 
public void init()
{
    // ... 
 
    super();
 
    // Hay que pasar el buffer a la función para mantener el ámbito
    JAEETablaTmp::createRecords(tmpTable, desde, hasta);
 
    // ...
 
    // Enlazar el buffer con la tabla temporal
    JAEETablaTmp.linkPhysicalTableInstance(tmpTable);
}
Así podremos actualizar los datos posteriormente, en mi caso con la llamada a un botón en el formulario que obtiene parámetros de otros controles, de esta forma:
void clicked()
{
    JAEETablaTmp::createRecords(tmpTable, FromDate.dateValue(), ToDate.dateValue());
    JAEETablaTmp_ds.executeQuery();
}
Destacar cómo la variable temporal declarada en el formulario se pasa a la función que genera los datos para mantener siempre la referencia a la misma variable que está enlazada al origen de datos. La función gestiona los datos en esta misma variable, y la devuelve, de esta manera:
public static client JAEETablaTmp createRecords(
    JAEETablaTmp    _tmpBuffer,
    FromDate        _desde,
    ToDate          _hasta)
{
    // ...
 
    delete_from _tmpBuffer;
 
    while select DatePhysical, ItemId, sum(Qty)
        // ...
    {
        _tmpBuffer.clear();
        // ...
        _tmpBuffer.insert();
    }
 
    return _tmpBuffer;
}
Una particularidad que hay que tener en cuenta es que, en el momento de enlazar la tabla temporal con el origen de datos, la variable buffer no puede estar vacía, o el enlace no se realiza. Ésto no es ningún problema en el primer ejemplo, ya que simplemente no se mostrará ningún dato en el formulario; pero si utilizamos la segunda técnica y el enlace con la variable no se realiza correctamente,  posteriores actualizaciones de la variable no se verán reflejadas en el origen de datos, y tampoco se mostrará ningún error. Una forma sencilla de evitar esto es insertar un registro vacío en la tabla antes de realizar el enlace con el origen de datos:
public void init()
{
    // ... 
 
    super();
 
    // Hay que pasar el buffer a la función para mantener el ámbito
    JAEETablaTmp::createRecords(tmpTable, desde, hasta);
 
    // Si la tabla no tiene registros, la tabla no se enlaza!!
    if (!tmpTable)
        tmpTable.insert(); // IMPORTANTE!
 
    // Enlazar el buffer con la tabla temporal
    JAEETablaTmp.linkPhysicalTableInstance(tmpTable);
}
Espero que os sirva :D
Read More »

Libro: Microsoft Dynamics AX 2012 R2 Services

Después de un parón en la publicación de contenidos, debido a un gran proyecto que verá la luz en los próximos días/semanas, vuelvo a la carga con la revisión de un libro escrito por Klaas Deforche y Kenny Saelen y publicado por Packt Publishing, quienes me han echo llegar una versión digital. Tiene este aspecto:

Microsoft Dynamics AX 2012 Services

Este libro es una especie de segunda parte del que ya mencioné (y recomendé encarecidamente) hace algún tiempo titulado Microsoft Dynamics AX 2012 Services. El contenido es muy parecido e igual de recomendable. Esta segunda versión es más larga que el primero, por lo que abunda más en ciertos contenidos aportando más detalles, aunque el contenido en general es prácticamente el mismo, salvo algunos detalles propios de la revisión R2, que en cuanto a servicios web no son muy numerosos.

Aún así, como digo, es un libro muy recomendable, igual que lo era la primera parte. Cuenta con dos autores ya reconocidos y con la experiencia previa de la primera versión, y con un equipo de revisores de primera, así que el contenido esta bien escrito y bien estructurado, sobre un tema que es obligatorio para cualquier implantación de Microsoft Dynamics AX 2012, como son los servicios web.

Si ya compraste la primera versión, probablemente esta última no te aporte grandes novedades, salvo los detalles en los que profundiza más, y las escasas novedades de la R2. Si en su día no lo compraste, claramente recomiendo comprar esta segunda versión porque la lectura es muy interesante.

Read More »

Microsoft Dynamics AX 2012 R3 Demo VM V1

Microsoft Dynamics AX 2012 R3 Ya se ha publicado la máquina virtual demo de la también recién publicada Microsoft Dynamics AX 2012 R3. Esta máquina virtual viene, como de costumbre, actualizada con las últimas versiones de todo el software (Incluido Windows 2012 R2 y Microsoft SQL Server 2014) y con datos de prueba de las nuevas funcionalidades de esta versión, que son numerosas. Se puede descargar de los siguientes enlaces: Sin duda la gran ventaja de esta versión es la posibilidad de desplegar la máquina virtual directamente en Azure desde nuestra cuenta de , algo que se agradece viendo los enormes requerimientos de hardware que tienen las últimas versiones de la máquina demo. Los compañeros de TrucosAX han publicado una guía paso a paso de como realizar ese sencillo despliegue, muy recomendable:  
Read More »