…y tú, ¿Qué máquina virtual necesitas?…

Navegando el otro día por la red encontré un interesante recurso muy útil para todos los que nos necesitamos probar cosas, y muchas veces no podemos probarlas porque no tenemos tiempo para crear la infraestructura necesaria. Este recurso no es otra cosa que una lista de discos duros virtuales en las que tenemos instalados y listos para probar distintas plataformas,tecnologías y herramientas de Microsoft. Podéis acceder a la página con los discos duros en este enlace. De todos modos, os dejo aquí el listado de discos duros virtuales disponibles por producto.

A disfrutar…

ADO.NET EF: …enredando y más ejemplos (I)

En el último post sobre ADO.NET EF & LINQ To SQL os hablaba de que ya había algún ejemplo concreto para la Beta1 del SP1 de Visual Studio 2008. En concreto os hablaba del ejemplo ADO.NET Entity Framework Query Samples que está disponible en MSDN Code Gallery. El caso es que el equipo de ADO.NET nos comenta en una de sus últimas entradas que se han actualizado todos los ejemplos que había para ADO.NET EF a la Beta1 del SP1 de Visual Studio 2008. Entre los ejemplos actualizados, y que tendré que probar, está la herramienta eSqlBlast de la que os hablé hace tiempo y que me pareció espectacular…pero analizando un poquillo ADO.NET EF Query Samples, he podido comprobar que tal y como se comenta en la página del proyecto es una interesante herramienta de aprendizaje y de pruebas de los distintos tipos de consultas que podemos realizar contra un modelo de ADO.NET EF.

ADO.NET Entity Framework Query Samples

Una vez descargado el proyecto, y tras retocar la cadena de conexión a la BD NorthwindEF del App.Config, no basta con compilar y ejecutar la aplicación para empezar a probarla. La aplicación contempla tres grandes secciones:

image

  • Entity SQL over ObjectQuery<T>, que nos permite definir consultas utilizando servicios del objeto. Esta alternativa permite devolver estructuras de información del EDM a través del método CreateQuery asociado al objeto ObjectContext (y que implementa una interfaz de tipo ObjectQuery<T>), que acepta una instrucción eSQL o LINQ To Entities con parámetros que define una consulta que recuperará una cierta lista de entidades.
  • LINQ To Entities, que nos permite definir consultas LINQ contra el Entity Data Model definido. LINQ To Entities que nos dota de toda la potencia y capacidades de LINQ sobre ADO.NET Entity Framework, así como funcionalidad de ORM (Object Relational Model), de manera que los desarrolladores pueden materializar sus entidades en tipos del CLR y programar de forma más sencilla contra el EDM y la base de datos.
  • Query Builder Method, que se asienta en la capacidad que da la clase ObjectQuery para definir de forma más flexible consutas de LINQ To Entities o Entity SQL contra el EDM. Otro punto muy importante de ObjectQuery es que implementa una serie de query builder methods que facilitan la construcción de consultas de forma equivalente a lo que podemos hacer con eSQL.
image image  

image

Para cada tipo de consulta no sólo veremos su implementación en C# y el resultado, sino también la traducción interna que hace de la sentencia LINQ y el comando T-SQL (por si había dudas, la consulta que he probado en el ejemplo ya tiene su complejidad) que se envía a la BD.

image image

Cómo veis, ADO.NET EF Query Samples es una aplicación realmente pensada para agilizar el aprendizaje de distintas formas de realizar consultas a EDM’s.

Enredando un poquillo con ADO.NET EF

Para finalizar el post, os voy a contar algunas cosas que he podido probar de ADO.NET EF en la versión Beta1 del SP1 de Visual Studio 2008. Algunas de estas cosas ya nos las anticipo Unai en este post:

  • Nuevo diseñador, más ligero y funcional:
ADO_NET_EF_SP1_2 ADO_NET_EF_SP1_3  

ADO_NET_EF_SP1_4

  • Los ficheros de metadatos ya no aparecen físicamente en el directorio bin, sino que forman parte del ensamblado:

ADO_NET_EF_SP1_5

Además de esto, otra aspecto interesante que he intentado probar pero que no hay manera (no se la razón) es como llamar a un procedimiento almacenado…como esto espero contarlo en el próximo post, sólo os diré que una de las formas es mapeando el SP definido en la capa storage a una función importada en la capa conceptual…y hasta aquí puedo leer 😉

ADO_NET_EF_SP1_6 ADO_NET_EF_SP1_7  

ADO_NET_EF_SP1_8Y hasta aquí llega lo que os quería contar hoy sobre ADO.NET EF. Espero que el post os haya resultado interesante.

Windows 7: …ya tenemos los primeros detalles…

Aunque ya había leído algo acerca de que Microsoft está trabajando en la nueva versión de su S.O y que vendrá a sustituir a nuestro querido Windows Vista, no ha sido hasta hoy cuando he visto una primera noticia oficial en la que ya se empieza a hablar de detalles de la nueva versión, denominada de momento Windows 7. En concreto, la noticia aparecida en la sección de tecnología del diario El Mundo se hace eco del hecho de que Windows 7 estará optimizado para funcionar con pantallas táctiles gracias a la tecnología Multi-Touch y que posibilitará visualizar fotografías o navegar en Internet a golpe de dedo…como siempre, ya tenemos los primeros vídeos con características que podrían aparecer en la nueva versión de Windows (no he encontrado ninguno en el que se demuestre la funcionalidad táctil que se describe en el artículo).

Por cierto, como podréis leer en la noticia, la previsión de lanzamiento de Windows 7 es finales del año que viene. De esta manera, parece que Microsoft es fiel a su palabra de reducir el tiempo de desarrollo de las nuevas versiones de su S.O.

WSS 3.0 & MOSS: Extendiendo las capacidades de búsqueda (III)!

Como toda saga debería tener su fin, con este post vamos a completar la serie de artículos sobre como es posible ir más allá de las capacidades de búsqueda out-of-the-box en plataforma SharePoint que iniciamos con las partes I y II. En este post haremos un recorrido por la tercera opción que nos ofrece SharePoint para extender las capacidades de búsqueda: los servicios web de búsqueda. Empecemos.

Query Web Service en SharePoint

Además de poder realizar consultas a través del modelo de objetos, la plataforma SharePoint permite realizar búsquedas a través del Query Web Service. Esta opción de búsqueda soporta las dos posibilidades vistas para realizar búsquedas mediante el modelo de objetos: SQL Syntax y Keyword Syntax. Entonces, ¿cuándo usamos el Query Object Model y cuando el Query Web Service? La respuesta es bastante sencilla. Usaremos la primera opción cuando la aplicación de búsquedas resida en el mismo servidor que está ejecutando WSS 3.0 o MOSS. Usaremos la segunda opción cuando se trate de aplicaciones remotas.

Los servicios web de búsqueda de WSS 3.0 & MOSS nos permite acceder a las funcionalidades de búsqueda desde aplicaciones cliente que estén fuera del contexto de sitios de SharePoint:

Los métodos web para WSS 3.0 y MOSS son los mismos, si bien, y como ya sabemos, las capacidades de búsqueda son mucho más potentes en MOSS que en WSS 3.0.

Uso del Query Web Service

Para probar esta funcionalidad, partiremos de la misma aplicación web que vimos en el post anterior, al que vamos a añadir al proyecto un nuevo ítem de tipo Web Form. Abrimos la página que acabamos de crear en modo de diseño y añadimos los siguientes elementos (ver Figura):

  • Un control de tipo Table de la sección HTML de la Toolbox.
  • Un control de tipo TextBox en el que configuramos la propiedad TextMode con la opción MultiLine.
  • Un control de tipo DrowDownList.
  • Un control de tipo Label en el que configuramos la propiedad Text con el texto Tipo de Consulta.
  • Un control de tipo TextBox en el que configuramos la propiedad TextMode con la opción MultiLine.
  • Un control de tipo Button en el que configuramos la propiedad Text con el texto Buscar.
  • Un control de tipo Label.
  • Un control de tipo GridView.

Como veis, el aspecto de la web es casi igual al de la realizada en el post previo…de hecho el copy & paste ha sido radical 😛 (cuestión de aprovechar tiempos).

image image

Una vez que hemos diseñado la página de búsquedas en la que habilitaremos SQL Syntax, nos vamos a la vista de código de la misma presionando F7. En esta vista de código vamos a añadir toda la lógica necesaria para poder probar la funcionalidad Query Web Service:

  • Lo primero que vamos a hacer es añadir la referencia al servicio web de búsqueda. Para ello, utilizamos la opción Add Web Reference… disponible cuando clic con el botón derecho del ratón sobre el nombre de la solución.
  • Hacemos clic sobre la opción Web services on the local machine.
  • Buscamos el servicio web de búsquedas de MOSS. Como hemos comentado, la url característica de este servicio web es: http://Nombre_Servidor/[Sites/][Site_Name/]_vti_bin/search.asmx.
  • Hacemos clic sobre el servicio web search y en la siguiente pantalla le damos a la referencia web el nombre de QueryWebServiceProxy.
  • Pulsamos Add Reference y ya tentemos añadido el servicio web de búsqueda de MOSS a nuestro proyecto.
image image  

image

Una vez que hemos añadido la referencia web al servicio de búsqueda de MOSS, ya podemos comenzar a añadirle la lógica necesaria a la página ASP.NET:

  • Añadimos las siguientes constantes a la clase parcial asociada a la página:

    #region Variables & Constates

    //Constantes valores combo

    const string ID_QUERY = “ID_Query”;

    const string NOMBRE_QUERY = “Query”;

    public const string TIPO_QUERY0_ID = “Q0”;

    public const string TIPO_QUERY0_TEXT = “Seleccione un tipo de query…”;

    public const string TIPO_QUERY1_ID = “Q1”;

    public const string TIPO_QUERY1_TEXT = “Keyword Query”;

    public const string TIPO_QUERY2_ID = “Q2”;

    public const string TIPO_QUERY2_TEXT = “Búsqueda por Scope”;

    public const string TIPO_QUERY3_ID = “Q3”;

    public const string TIPO_QUERY3_TEXT = “Búsqueda por Scope y Campo”;

    public const string TIPO_QUERY4_ID = “Q4”;

    public const string TIPO_QUERY4_TEXT = “Búsqueda con LIKE”;

    public const string TIPO_QUERY5_ID = “Q5”;

    public const string TIPO_QUERY5_TEXT = “Búsqueda con CONTAINS y *”;

    public const string TIPO_QUERY6_ID = “Q6”;

    public const string TIPO_QUERY6_TEXT = “Búsqueda con FreeText”;

    public const string TIPO_QUERY7_ID = “Q7”;

    public const string TIPO_QUERY7_TEXT = “Búsqueda con FreeText y Op. Exclusión”;

    //Constantes para las queries

    public const string QUERY1 = “Introduzca la palabra clave a buscar…”;

    public const string XML_TAG_START1 = “<QueryPacket xmlns=’urn:Microsoft.Search.Query’>”

            + “<Query><SupportedFormats><Format revision=’1′>”

            + “urn:Microsoft.Search.Response.Document:Document</Format>”

            + “</SupportedFormats><Context><QueryText language=’en-US’ type=’STRING’>”;

    public const string XML_TAG_START2 = “<QueryPacket xmlns=’urn:Microsoft.Search.Query’>”

                + “<Query><SupportedFormats><Format revision=’1′>”

                + “urn:Microsoft.Search.Response.Document:Document</Format>”

                + “</SupportedFormats><Context><QueryText language=’en-US’ type=’MSSQLFT’>”;

    public const string XML_TAG_END = “</QueryText></Context></Query></QueryPacket>”;

    public const string QUERY2 = “SELECT Rank, Title, Author, Size, Path, Description” +

                            ” FROM SCOPE() WHERE \”scope\”=’All Sites'”;

    public const string QUERY3 = “SELECT Rank, Title, Author, Size, Path, Description” +

                            ” FROM SCOPE() WHERE \”scope\”=’All Sites'” +

                            ” AND  Author=’LitwareInc Administrator’ ORDER BY Rank DESC”;

    public const string QUERY4 = “SELECT Rank, Title, Author, Size, Path, Description” +

                            ” FROM SCOPE() WHERE \”scope\”=’All Sites'” +

                            ” AND TITLE LIKE ‘Bla%’ ORDER BY Rank DESC”;

    public const string QUERY5 = “SELECT Rank, Title, Author, Size, Path, Description” +

                            ” FROM SCOPE() WHERE CONTAINS (‘\”Bla*\”‘)”;

    public const string QUERY6 = “SELECT Rank, Title, Author, Size, Path, Description” +

                            ” FROM SCOPE() WHERE \”scope\”=’All Sites'” +

                            “AND FreeText (‘Bla%’) ORDER BY Rank DESC”;

    public const string QUERY7 = “SELECT Rank, Title, Author, Size, Path, Description” +

                            ” FROM SCOPE() WHERE \”scope\”=’All Sites'” +

                            “AND FreeText (‘Bla% -CRM’) ORDER BY Rank DESC”;

    #endregion

Como vemos, estas constantes nos van a permitir realizar varios tipos de consultas mediante utilizando el servicio web de búsqueda. Las consultas son las mismas vistas con SQL Syntax y Keyword Syntax, pero con la particularidad de que las envolveremos con unas etiquetas XML particulares:

  • Consultas utilizando una palabra clave.
  • Consultas a un determinado scope (en este caso All Sites).
  • Consultas a un scope y filtrando por un cierto campo (Author).
  • Consultas utilizando la cláusula LIKE que permite extender las búsquedas en SharePoint al habilitar el uso de operadores comodín (%).
  • Consultas utilizando el predicado CONTAINS(), que permite buscar el término de búsqueda utilizando caracteres comodín (*) y utilizando proximidad. Con este operador se utiliza habitualmente el comodín *.
  • Consultas utilizando el predicado FreeText(), que permite buscar el término de búsqueda dentro de los documentos.

Además, en el código anterior también podemos observar lo siguiente:

  • Hay dos tipos de etiquetas XML que envuelven estos tipos de consultas. Por un lado tenemos:

    public const string XML_TAG_START1 = “<QueryPacket xmlns=’urn:Microsoft.Search.Query’>”

            + “<Query><SupportedFormats><Format revision=’1′>”

            + “urn:Microsoft.Search.Response.Document:Document</Format>”

            + “</SupportedFormats><Context><QueryText language=’en-US’ type=’STRING’>”;

Esta etiqueta lo que indica es que la consulta a ejecutar es de tipo STRING y es el el propio componente de búsqueda de MOSS el que se encarga de construir la query a partir de la palabra clave especificada.

  • Por otro lado, nos encontramos con:

    public const string XML_TAG_START2 = “<QueryPacket xmlns=’urn:Microsoft.Search.Query’>”

                + “<Query><SupportedFormats><Format revision=’1′>”

                + “urn:Microsoft.Search.Response.Document:Document</Format>”

                + “</SupportedFormats><Context><QueryText language=’en-US’ type=’MSSQLFT’>”;

Esta etiqueta indica que la consulta a ejecutar es de tipo MSSQLFT, es decir, es la lógica de nuestra aplicación la que se encarga de construir la consulta parametrizada y pasársela al componente de búsqueda de SharePoint.

  • Los resultados se ordenan utilizando la cláusula ODER BY Rank DESC, es decir, los resultados se devuelven ordenador de forma descendente por la propiedad Rank que indica el nivel de raking de un cierto resultado devuelto por el motor de búsquedas de SharePoint (MOSS en este caso).
  • En alguna de las consultas se utiliza el operador de exclusión -, que nos permite especificar que se excluyan aquellos resultados que contengan el término que aparece a continuación del operador.

En el evento Page_Load() de la página ASP.NET añadimos el siguiente código:

   protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

        { 

            this.Label1.Text = “”;

            this.Button.Enabled = false;

            //Filling the combo

            DataTable dtlQueries = new DataTable();

            dtlQueries.Columns.Add(ID_QUERY);

            dtlQueries.Columns.Add(NOMBRE_QUERY);

            Random rdIDProducto = new Random();

            DataRow dtrFila;

            //Default Data

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY0_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY0_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //First Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY1_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY1_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Second Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY2_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY2_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Third Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY3_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY3_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Fourth Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY4_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY4_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Fith Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY5_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY5_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Sixth Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY6_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY6_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Seventh Query

            dtrFila = dtlQueries.NewRow();

            dtrFila[ID_QUERY] = TIPO_QUERY7_ID;

            dtrFila[NOMBRE_QUERY] = TIPO_QUERY7_TEXT;

            dtlQueries.Rows.Add(dtrFila);

            //Adding the data to the dropdownlist

            this.DropDownList1.DataSource = dtlQueries;

            this.DropDownList1.DataTextField = NOMBRE_QUERY;

            this.DropDownList1.DataValueField = ID_QUERY;

            this.DropDownList1.DataBind();

            this.DropDownList1.AutoPostBack = true;

            this.DropDownList1.SelectedItem.Value = TIPO_QUERY0_ID;

        }

    }

Como vemos, el código anterior nos permite configurar en la primera carga de la página los parámetros iniciales de los controles de la misma. En particular, estamos realizando las siguientes tareas:

  • Rellenar el control DropDownList con los distintos tipos de consultas que vamos a realizar.
  • Configuramos la propiedad AutoPostBack a true para que la página se enteré de que el usuario ha seleccionado una cierta opción y se llame al correspondiente manejador.
  • Especificar el valor del DropDownList que se muestra por defecto.

Codificamos el manejador del evento SelectedIndexChanged del control DropDownList añadiéndolo directamente en la vista de código de la página o bien haciendo doble clic sobre dicho control desde la vista de diseño de la página:

  protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)

    {

        if (this.DropDownList1.SelectedItem.Value != “0”)

        {

            this.Label1.Text = “”;

            string sOpcionQuery = this.DropDownList1.SelectedItem.Value;

            switch (sOpcionQuery)

            {

                case TIPO_QUERY1_ID:                                                             

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY1;

                    break;

                case TIPO_QUERY2_ID:

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY2;

                    break;

                case TIPO_QUERY3_ID:

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY3;

                    break;

                case TIPO_QUERY4_ID:

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY4;

                    break;

                case TIPO_QUERY5_ID:

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY5;

                    break;

                case TIPO_QUERY6_ID:

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY6;

                    break;

                case TIPO_QUERY7_ID:

                    this.Button.Enabled = true;

                    this.TextBox1.Text = QUERY7;

                    break;

                default:

                    this.Label1.Text = “”;

                    this.Button.Enabled = false;

                    break;

            }

        }

        else

        {

            this.Label1.Text = “”;

            this.Button.Enabled = false;

        } 

    }

Con el código anterior, estamos pintando en el control TextBox de la página la consulta, seleccionada por el usuario.

Finalmente, codificamos el manejador del evento clic del control Button utilizando una de las dos opciones comentadas para el manejador SelectedIndexChanged del control DropDownList:

   protected void Button1_Click(object sender, EventArgs e)

    {

        try

        {

            int totalNumRecords=0;

            string keywordString = this.TextBox1.Text;

            string qXMLString;

            DataSet queryResults=new DataSet();

            QueryWebServiceProxy.QueryService queryService =

               new QueryWebServiceProxy.QueryService();

            queryService.Credentials = System.Net.CredentialCache.DefaultCredentials;

            if (this.DropDownList1.SelectedItem.Value==TIPO_QUERY1_ID)

            {

               qXMLString = XML_TAG_START1 + keywordString + XML_TAG_END;                

            }

            else

            {

                qXMLString = XML_TAG_START2 + keywordString + XML_TAG_END;         

            } 

            queryResults = queryService.QueryEx(qXMLString);

            totalNumRecords = queryResults.Tables[0].Rows.Count;         

            if (totalNumRecords > 0)

            {

                this.Label1.Text = “Número de coincidencias ” + totalNumRecords.ToString();

                this.GridView1.DataSource = queryResults.Tables[0];

                this.GridView1.DataBind();

            }

            else

            {

                this.Label1.Text = “No hay resultados para esta búsqueda”;

                this.GridView1.DataSource = null;

                this.GridView1.DataBind();

            }          

        }

        catch (Exception ex)

        {

            this.Label1.Text = ex.Message;

        }

    }

Como vemos en el listado del código (en negrita las partes clave), los pasos necesarios para realizar consultas utilizando el servicio web de búsqueda son los siguientes:

  • Definimos un objeto de tipo QueryService() a partir de la referencia creada al servicio web y que nos permitirá realizar los dos tipos de búsquedas comentados.
  • Especificamos las credenciales de acceso al servicio web de búsqueda (ponemos las credenciales por defecto).
  • En función de la opción seleccionada por el usuario, búsqueda por palabra clave o mediante una consulta SQL Syntax, parametrizamos de forma adecuada la consulta que tiene que ejecutar el servicio web de búsqueda de MOSS:
    • En el caso de Keyword Syntax, es el propio componente de búsqueda de MOSS el que se encarga de construir la query a partir de la palabra clave especificada.
    • En el caso de SQL Syntax, es la lógica de nuestra aplicación la que se encarga de construir la consulta parametrizada y pasársela al componente de búsqueda de SharePoint.

En cualquiera de las dos situaciones, la consulta se ejecuta mediante el método QueryEx() y el resultado devuelto (una colección de registros que cumplen las condiciones de búsqueda definidas) lo almacenamos en un objeto de tipo DatSet.

  • Sin más, comprobamos que hay resultados en el tabla con índice 0 del Dataset y los renderizamos en el control GridView e la página.

Probando la solución

Una vez diseñada la aplicación de búsquedas preparada para definir búsquedas el servicio web de búsquedas de MOSS, así como implementada la lógica de búsquedas, vamos a probar dos de las situaciones modelada:

  • Búsqueda mediante palabra clave:
    • Escogemos la opción Keyword query.
  • Búsqueda mediante SQL Syntax:

    o Seleccionamos la opción Búsqueda con FreeText y Op. de Exclusión.

image image

Y aquí concluye esta serie de post sobre extensibilidad de las capacidades de búsqueda en plataforma SharePoint. Espero que el tema os haya resultado interesante.

Microsoft Office soportará de forma nativa ODF en 2009!

Habitualmente suelo leer la sección de tecnología de el diario El Mundo (elmundo.es navegante), y que opino está bastante bien y actualizada en cuanto a temas y noticias tratadas. El caso es que acabo de leer lo que se puede calificar como una noticia excelente para la interoperabilidad (aunque no lo será tanto para los que han presionado lo indecible para que el formato Microsoft Office XML, OOXML,  se convirtiera en un estándar ISO) entre sistemas: Microsoft Office 2007 soportará con el service pack 2 Open Document Format (ODF) v1.1. Además de este, soportará XML Paper Specification y Portable Document Format (PDF), es decir, Microsoft sigue apostando por la interoperabilidad basada en estándares ampliando con estos nuevos soportes los 20 formatos de ficheros diferentes que soporta en la actualidad.

Como podéis leer en la noticia de El mundo, el SP2 de Microsoft Office 2007 está previsto para el primer semestre de 2009 y permitirá trabajar con archivos que usen estos formatos sin necesidad de tener que instalar ningún tipo de Add-In. Y no sólo eso, Microsoft prevé colaborar con la comunidad open source para que las versiones anteriores de Office (XP y 2003) puedan utilizar también ODF. En partícular, Microsoft se ha comprometido a mejorar el traductor OOXML-ODF SourceForge.net.

ADO.NET Entity Framework y LINQ To SQL: Ejemplos de las novedades del SP1 Beta 1!

Poco a poco empiezan a aparecer ejemplos de algunos de los cambios que vienen con el SP1 Beta 1 de .NET Framework 3.5. En esta ocasión, os dejo algunos recursos interesantes sobre el tema:

XNA Game Studio 3.0 CTP: Ahora también podemos crear juegos para el Zune!

Aunque no he probado a hacer cosas con XNA, navegando por la blogosfera me he enterado que Microsoft liberó el pasado 7 de mayo la primera CTP de XNA 3.0 Game Studio, específicamente preparada para crear juegos para su reproductor de música y video Zune:

Para probar esta primera CTP sólo se necesita Visual Studio C# 2008 Express o bien Visual Studio 2008 Standar Edition o superior. Como os he comentado, esta CRP sólo está operativa para Zune y Windows, y no para la XBox 360. Sin más, os dejo unos enlaces para los que seáis realmente intrépidos y queráis probar esta CTP: