Social Icons

jueves, 18 de diciembre de 2008

HRESULT: 0x80070094 ¿Pero de qué te quejas ahora SharePoint?

En mi caso SharePoint daba este error al intentar crear una nueva aplicación web. Nada, nada, tranquilididad. Se trata de el servicio de administración de IIS no está funcionando como Dios manda. Para comprobar que se trata de esto nos vamos a Inicio --> Herramientas administrativas --> Administración de Internet Information Services (IIS) y vemos que no rula.


Solución: Rápido y veloz nos vamos a Ejecutas: services.msc y buscamos el servicio llamado "Servicio de administración IIS" pulsamos reiniciar, aceptar y listo.


Si esto no funciona podemos reiniciar el server completo, y si eso tampoco surte efecto dicen que hay un hotfix de Microsoft que se encarga del tema. A mi me bastó con el reinicio del servicio. Al final tuve que resetear todos los web front end :(


Por cierto, si alguien me ha echado de menos es que he estado malito con conjuntivitis.

Publicar un comentario

martes, 9 de diciembre de 2008

Al fin aprendo a hacer RunWithElevatedPrivileges sin -2130575251

Para el que sepa es muy sencillo, y posiblemente ya todo el mundo sepa, pero yo me acabo de enterar hoy. Se acabó la tiranía de las impersonaciones con administradores.

El secreto es abrir el SPWeb con los privilegios elevados y con el AllowUnsafeUpdates=true, por supuesto, luego hay que cerrarlo todo y guardarlo en su cajita, para cuando nos vuelva a hacer falta, más o menos así:

private static void CreaNuevoDocumento()



{



SPWeb sCurrentElevatedWeb = null;



SPSite sElevatedSite = null;



SPListItem sNuevoItem = null;



SPSecurity.RunWithElevatedPrivileges(







delegate()



{

sElevatedSite =
new SPSite(SPControl.GetContextSite(Context).ID);

sCurrentElevatedWeb = sElevatedSite.OpenWeb();

});





sCurrentElevatedWeb.AllowUnsafeUpdates =
true;

sNuevoItem = CreateTempFile(sCurrentElevatedWeb);





sNuevoItem[
"Source"] = "Privilegios Elevados";

sNuevoItem[
"Id"] = "-1";

sNuevoItem.Update();





sCurrentElevatedWeb.AllowUnsafeUpdates =
false;

sCurrentElevatedWeb.Dispose();

sElevatedSite.Dispose();

}

Quiero hacer hicapié en que mientras menos cosas hagamos dentro del delegate menos posibilidades tendremos de que se queje con el rollo del ERROR CODE -2130575251, por ejemplo los SPListItem.Update(). El secreto es crear los objetos Elevados y cerrar el delegate para luego usarlos fuera.

¿Por qué? y ¿por qué no?

Publicar un comentario

jueves, 4 de diciembre de 2008

AllowPartiallyTrustedCallersAttribute, y otra vez descolocao

Si al cargar un webpart en una página de SharePoint te dice:

"Los ensamblados que implementan elementos Web de ASP.NET y que están instalados en una ubicación de confianza parcial, como el directorio de la Papelera de reciclaje, deben compilarse con AllowPartiallyTrustedCallersAttribute establecido para que la importación se realice correctamente"

¿A quién se le ocurre instalar ensamblados en la papelera de reciclaje, por Dios?

No padezcas, simplemente pon:

[assembly:System.Security.AllowPartiallyTrustedCallers()]

Encima del namespace y santas pascuas.

¿Alguien instala cosas en la papelera de reciclaje? No se de qué me quejo, para una vez en la vida que el literal del error no es "ERROR".

Publicar un comentario

Directiva de administración de la información: Caducidad

Hay veces que, dada su naturaleza, los elementos de una biblioteca son candidatos a ser desechados cuando tienen una antigüedad determinada.

SharePoint contempla añadir caducidad a los elementos de listas o bibliotecas a partir de los valores de un metadato tipo fecha del mismo y como es muy fácil hacerlo os contaré cómo.

Voy a elegir una biblioteca de documentos porque SharePoint te permite tomar como referencia para la caducidad la fecha de creación del documento se ve que "alguien" consideró que no tenía sentido tomar como referencia la fecha de creación de un elemento de lista. En el caso de usar un elemento de lista tendremos que usar un campo fecha que creemos nosotros, por ejemplo un campo Fecha de Creación que tome por defecto la fecha del día.

Bueno, a lo que vamos.

Nos dirigimos a la biblioteca de documentos en cuestión y nos vamos a "Configuración" y a "Configuración de Biblioteca de documentos". Una vez allí pulsamos en "Configuración de la directiva de administración de la información" un nombre cortito para que sea fácil de recordar.

Configuración de la directiva de administración de la información

Allí pulsamos "Definir una directiva" y "Aceptar" y en el menú que nos aparece seleccionamos "Habilitar Caducidad":

Habilitar Caducidad

Una vez allí seleccionamos "Período de tiempo basado en las propiedades del elemento" y el campo (Por ejemplo "Creado" o "Modificado"), el tiempo de caducidad y también seleccionamos "Realizar esta acción" y luego elegimos una de entre la lista de acciones (Por ejemplo "Eliminar" o "Eliminar").

Luego pulsamos "Aceptar" y listo.

¿No se han dado cuenta los muchachos de Microsoft de que la longitud del nombre "directivas de administración de la información" es inadecuada para un título? Si me hubieran encargado a mi la tarea de nombrarlo hubiese elegido algo como "Directivas de Administración de la Información de Elementos que Pueden Ser o No Documentos y Que Se Encuentran Contenidos en Bibliotecas o Listas de SharePoint Según su Idiosincrasia".

Publicar un comentario

jueves, 27 de noviembre de 2008

NLB & Sharepoint: Best Practices

Parece simple pero no he encontrado en internet a nadie que se moje en el tema de Balanceo de carga de red y SharePoint.


Bueno, esto hace pensar que es un tema escabroso y que habría que estar loco para meterse. Estar loco o tener muy poco que perder y en mi caso ambas son ciertas.


En 0,2 para no perder tiempo en explicar una cosa que no controlo quiero decir que aún controlo menos esto que las otras cosas que explico.



  • Montaremos NLB en todos los Web Front End

  • El modo de operación del cluster deberá ser Multicast (Para ahorrarnos hardware, básicamente)

  • Configuraremos el NLB con afinidad (obviamente por ser servidor de SharePoint)


    • Si va a servir a una intranet la configuraremos en tipo "Single"

    • Si va a servir a internet la configuraremos en tipo "Class C"

Y eso es todo lo que he sacado en claro.


He colgado el post antes de que se me olviden las configuraciones, pero todavía no está probado. Si veo que todo falla lo corregiré y si veo que todo explota lo borraré y pasaré vergüenza durante una franja temporal comprendida entre los 2 y los 5 minutos.


Sí, lo de las mejores prácticas era un farol, pero no da confianza poner en el título "NLB & Sharepoint: Best Practices (in case they work)"

Publicar un comentario

miércoles, 26 de noviembre de 2008

Los resultados más probables son tu Best Bet

Los best bets o como se tradujeron al castellano “Resultados más probables” son muy útiles, por lo menos a mi me gustan.

¿No os ha pasado, por ejemplo, que en las estadísticas de búsqueda de vuestro sitio veis consultas como “Teléfono”, “Dirección”, “Contacto”?, casi seguro, si vuestro sitio no trata de telefonía, vectores o pegamento que vuestros usuarios se encuentran solos en sus casas y quieren hablar con vosotros.

O por ejemplo, que tengamos una página sobre la etiqueta en una fiesta de bonobos de la cual estamos especialmente orgullosos y no nos gustaría que ningún usuario que buscase temas relacionados con “Monos” en nuestro portal se la perdiese.

Quizás nos convendría poder encaminar a los usuarios a una página determinada cuando se introdujesen ciertos términos en la búsqueda para que no se mareasen entre tantos resultados…

Pues por una vez, y sin que sirva de precedente, es facilísimo.

En la configuración del sitio clickamos en Palabras clave de búsqueda:

Agregar resultado más probable

Una vez allí pulsaremos sobre Agregar palabra clave y rellenaremos el formulario. Debemos pulsar sobre el link Agregar resultado más probable en donde se nos pedirá que introduzcamos los datos del link:

Agregar palabra clave

Después de esto ya puedes pulsar aceptar unas cuantas veces e ir derechito al sitio de búsqueda para ver cómo te ha quedado.

El mío quedó así:

Resultados de búsqueda con Best Bets de erChan

Mira qué bien y que pronto.

Bueno y con esto me despido hasta la próxima, que espero que no se demore tanto, que ya había quien pensó que no iba a seguir con el blog….

Saludos cordiales, Kind Regards, Zaijian.

Publicar un comentario

viernes, 14 de noviembre de 2008

Mapeo de Hex para CAML definitivo

Veo que es un tema recurrente (por las consultas que me llegan del google) el tema del mapeo de caracteres No-US para los nombres de los campos en las consultas CAML.

El mes pasado hice una burda primera aproximación al tema pero se me quedó en el tintero hacer una función que lo solucionase de forma más global. Pues bien, aprovechando que hoy estaba solo en casa como Marta Sánchez o como Macaulay Culkin tenía tiempo pues he decidido dejar zanjado el tema.

/// <summary>
///
Normalizes the string passed replacing the non standard
/// charaters by Sharepoint HEX code
/// </summary>
///
<param name="str">Works great with Field Names and CAML
/// Queries :D
</param>
static string fieldName2Caml(string str)
{
int i = 0;
while (i < color="#0000ff"> if ((str[i] >='0' && str[i] <= '9')
(str[i] >=
'a' && str[i] <= 'z')
(str[i] >=
'A' && str[i] <= 'Z'))
i++;
else
{
str = str.Substring(0, i) +
string.Format("_0x00{0}_", string.Format("{0:X}",
Convert.ToInt32(str[i]))).ToLower() +
str.Substring(i+1);
i += 8;
}
}
return str;
}

Hala y gracias a esto podremos transformar cualquier nombre de columna en castellano con sus acentos y con sus eñes y con sus espacios al formáto válido en las consultas CAML de Sharepoint.

Los comentarios del principio se los dedico al Yeyo, para que vea que pese a haber leído el manual de estilo no lo aplico porque para eso este blog esss Miiio.


No se porqué me he acordado de Batman y del Señor de los anillos.


Publicar un comentario

lunes, 10 de noviembre de 2008

Y desde ahora todo por CAML

Las consultas a SPList por CAML ofrecen muchas ventajas, con lo que he sido yo, que iteraba todo siempre... la primera de ellas es la velocidad a la que se ejecutan, la segunda y, en según qué casos, más importante que la primera es la potencia que nos ofrecen.

Lo último que he tenido que hacer es un buscador en el que dados un parámetro y una lista:

  • Si el parámetro es vacío: Muestra los elementos vigentes de la lista.
  • Si el parámetro es "lst": Muestra un listado de todos los elementos.
  • Si el parámetro es otra cosa: Muestra los elementos que contienen la cadena parámetro en su título o en su descripción.

Todos los resultados se muestran ordenados por fecha de forma ascendente.

Es sorprendente lo simple que se hace una cosa así con las CAML Queries.

protected void buscaCAML(SPList lista, string parametro, HtmlTextWriter writer)
{
SPQuery query = new SPQuery();
string ordenado = "";

string consultaParametro = "" +
"{0}
" +
"{0}
" +
"
{1}";
consultaParametro = string.Format(consultaParametro, parametro, ordenado);

string consultaFechas = "" +
"
" +
"
{0}";
consultaFechas = string.Format(consultaFechas, ordenado);

if (string.IsNullOrEmpty(parametro))
query.Query = consultaFechas;
else if (parametro == "lst")
query.Query = ordenado;
else
query.Query = consultaParametro;

foreach (SPListItem anuncio in lista.GetItems(query))
writer.Write(anuncio["Título"].ToString());
}

Obviamente ésto es más rápido que cualquier método iterativo de búsqueda+ordenación, lo que queda por demostrar es que es más rápido que una consulta SQL al motor de búsqueda cuando la lista es grande...
Se admiten apuestas.


(Por cierto, el Highlighter es rápido y cómodo pero mi método anterior es más bonito cuando se trata de C#)

Publicar un comentario

lunes, 3 de noviembre de 2008

Controlar el consumo de memoria del SQL Server

Como habréis notado, en los servidores de pre-producción el SQL Server 2005 agota en un ratito toda la memoria que tengamos. Si apagamos la máquina y le ponemos más RAM el SQL vuelve a comérsela otra vez provocando en nosotros esa desagradable sensación de bucle infinito. Y lo peor es que da igual que la base de datos de contenido ocupe 100MB, el SQL ocupará 1GB antes de que nos demos cuenta.

En estos casos a mi me gusta bajarle un poco los humos y limitarle la cantidad de memoria que puede utilizar, así:

1.- Nos vamos al SQL Server Management Studio y abrimos las propiedades de la instancia en la que estamos trabajando:

Propiedades de la instancia de SQL

2.- Una vez allí vamos a la configuración de Memoria y retocamos los valores de Memoria mínima del server y Memoria máxima del server como mejor corresponda a nuestro server. A mi me gusta poner algo como 128/512, así:

Server Memory Options Minimum-Maximum

Y ya está, con esto hemos terminado con la vampirización de la memoria de nuestro server por parte del conde SQLServer.

Por supuesto también es posible que en los servidores de producción os convenga que el SQL Server tenga bastante memoria para él, en ese caso podréis poner la combinación que os apetezca, 2048/15360 por ejemplo en un server de 16GB.

Ah otra cosa, los Windows 2003 Server Enterprise con más de 3GB funcionan mejor si editamos el fichero c:\boot.ini y añadimos después de donde pone /fastdetect un /3G quedando el final de la línea

/noexecute=optout /fastdetect /3g

Publicar un comentario

viernes, 31 de octubre de 2008

Mantenimiento de bases de datos de SharePoint

Las bases de datos son el corazón de SharePoint y a él también le gusta tener sano su corazoncito.

Para ello, lo que yo suelo recomendar a los administradores es que ejecuten esta serie de comandos una vez al mes por lo menos.


-- Seleccionamos base de datos de contenido
use WSS_Content
GO
-- Comprobamos la consistencia de la base de datos
dbcc checkdb
GO

-- Comprobamos la fragmentación
SELECT * FROM sys.dm_db_index_physical_stats
(DB_ID(N'WSS_Content'), OBJECT_ID(N'AllDocs'), NULL, NULL , 'DETAILED');
GO

-- Defragmentamos si alguno de los valores supera el 10% (Que va a ser siempre)
ALTER INDEX ALL ON AllDocs
REBUILD WITH (FILLFACTOR = 70, SORT_IN_TEMPDB = ON,
STATISTICS_NORECOMPUTE = ON)
GO

-- Comprobamos la fragmentación para sentirnos orgullosos al ver que se ha corregido
SELECT * FROM sys.dm_db_index_physical_stats
(DB_ID(N'WSS_Content'), OBJECT_ID(N'AllDocs'), NULL, NULL , 'DETAILED');
GO

-- Y por último "encogemos" la base de datos para compactarla y reducir su peso
DBCC SHRINKDATABASE (0, 20, NOTRUNCATE)
GO


Una pena que no salgan los colores del SQL Query, pero qué se le va a hacer.

Éstas querys están aprobadas por microsoft y se pueden hacer en caliente, obviamente es mejor hacerlas cuando el servidor no está a tope.

Algo que a Microsoft no le gusta nada es que trunquemos el log de la base de datos, pero es que hay veces que para una base de datos de 500 megas tenemos un log de 5 gigas y eso no es mu normal. En estos casos podemos hacer:

BACKUP LOG WSS_Content WITH TRUNCATE_ONLY
Que me perdone Steve Ballmer

Y otra cosa que podemos hacer ya que estamos aqui es curiosear por las bases de datos...

-- Miramos el tamaño del/los sitios (en MB)
SELECT FullUrl, (DiskUsed/(1024*1024)) AS DiskMB
FROM Sites
ORDER BY Diskused DESC
GO

-- Miramos el TOP10 de bibliotecas (en MB)
SELECT TOP 10 D.DirName, (S.Size/(1024*1024)) AS DiskMB
FROM ALLDOCS as D, AllDocStreams as S
WHERE D.Id=S.Id
ORDER BY S.Size DESC
GO
por ejemplo.



Bueno, me voy a comer.
Publicar un comentario

jueves, 30 de octubre de 2008

Huawei E270 y Vista x64

Hace un par de semanas que tengo este módem y pese a que pone claramente en la caja que es "Compatible con Windows Vista" he comprobado, triste, que no va bien Windows Vista x64. Tras darme cuenta no dudé en ponerme en contacto con el servicio técnico de Telefónica Movistar que, no sin antes hacerme perder un par de horas de tiempo y obligarme a pseudo-comunicarme con más de 5 personas, me informó que Huawei no da soporte para este dispositivo de internet móvil y Vista x64 y que mi única elección lógica a partir de ese momento era morirme de peste.

Bien, para los que estén en mi misma situación os comunicaré que HAY ESPERANZA.

Con un poco de paciencia y suerte he conseguido instalarlo y que funcione, sin necesidad de descargar drivers ni nada, y en un alarde de valentía lo desinstalaré y volveré a instalarlo sacando pantallazos ante sus atónitos ojos. Ojalá con un poco de suerte los de Movistar se lo lean y aprendan también a hacerlo de forma que llamar sirva para algo.

Bien, procedo...

1.- Cuando conectamos por primera vez el módem se nos muestra la ventanita de "Auto Play". Nos mostramos sumisos e instalamos el "Escritorio Movistar".

image

No os guío por el procedimiento de instalación porque seguramente ya lo habréis sufrido infinitas veces y os lo sabéis de memoria.

2.-Cuando terminamos, desilusión, como se ve en la parte de abajo: "Ningún dispositivo disponible"

image

No pasa nada, hay luz al final del túnel.

3.- Abrimos el explorador y entramos en la nueva unidad de CD que se nos crea con el iconito de Movistar (botón derecho-->Explorar).

image

Desde allí nos vamos al directorio Drivers y copiamos la carpeta WinVista64 a algún sitio que nos sea fácil recordar, por ejemplo nuestro escritorio.

4.- Nos vamos a panel de control y a Administrar Dispositivos.

Allí desinstalamos la unidad de CD "HUAWEI Mass Storage USB Device" (botón derecho--> Desinstalar). Nos pide reiniciar pero le decimos que No.

image

Y luego, lo mismo con el "Dispositivo USB de almacenamiento masivo" (o como sea que lo ponga el windows en castellano). En mi máquina es así:

image

Ahora cuando nos pida reiniciar ya le podemos decir que Sí y reiniciamos.

5.- Unos momentos más tarde al volver a logarnos nos dirá que ha encontrado un nuevo hardware y que si queremos instalar los drivers.

Haremos click en "Localizar e instalar los drivers (Recomendado)" --> luego a "No tengo un disco, enséñame otras opciones" y desde allí a "Buscar el driver en mi PC (Avanzado). Todos estos textos seguramente variarán en la versión castellano, usad sus equivalentes.

image

Allí ponéis la dirección donde guardásteis la carpeta de los drivers y le dais a Siguiente.

El driver se instala mágicamente. Luego os volverá a decir que ha encontrado nuevos drivers y deberéis repetir la operación (son 3 o 4 veces)

6.- Una vez hecho ésto podéis abrir el "Escritorio Movistar" y OHH Maravilla, os pide vuestro ping y ya tenéis allí vuestro modem.

image

Bueeeno, me conecto y lo subo desde aquí mismo. Saludos desde el aeropuerto del Prat.

Si que es verdad que éste post es totalmente off-topic, pero como el blog es mío...

Publicar un comentario

jueves, 23 de octubre de 2008

Creación de workflows con SharePoint Designer

¿Quién dice que en la página de Office Online no se publica nada interesante?.


Por fin hay un curso donde se explica como está mandado la forma de hacer flujos complejos con el Microsoft SharePoint Designer. ¡Es sorprendente! Lo que siempre quise saber y nunca me atreví a preguntar y un par de cosas que no se me habían ocurrido.


Os copio una foto del cuadro de mando para que vayáis abriendo boca:


Dashboard de Design a document review workflow solution



En la página se explica cómo realizar un flujo de revisión de documentos con sus formularios, sus mensajes de correo personalizados a los participantes para que estén todos informaditos, asignaciones de tareas a los usuarios implicados, un flujo secundario que volverá a avisar a los revisores si superan una fecha tope y no han mandado su aprobación (o bien asigna la tarea a un participante de seguridad), si a la mayoría de los revisores les parece bien asigna una tarea al revisor final, mientras que otro workflow va anotando todos los cambios en un cuadro de mando (dashboard) la mar de vistoso. Y para terminar, encima nos dice cómo guardar el sitio como plantilla para poder volver a usarlo cuando nos parezca, lo que son 14 pasos, vamos.


¡GENIAL!


Los vídeos son en inglés, pero se entienden perfectamente y no son en plan comercial como nos tienen acostumbrados, nada de eso, van al grano.


Diseña una solución de flujo de revisión de documentos con Designer


Gracias Stephen Howard, quienquiera que seas...

Publicar un comentario

miércoles, 22 de octubre de 2008

Edición de ámbitos en la búsqueda avanzada de MOSS para dummies

Como hoy no tengo muchas ganas de postear vamos con algo vistoso y facilón (si sabes cómo hacerlo).

Empezaré con el sitio de Búsqueda Avanzada por defecto. Lo primero que tenemos que hacer es quitar lo de las búsquedas por idiomas, ¿quién decidió que los tres idiomas que deberían de aparecer por defecto fueran Español, Alemán y Francés? pa haberlo matao.

Como es natural, lo primero que tenemos que hacer es quitar eso de los idiomas a la mayor brevedad posible. Editamos la página y nos vamos a las propiedades del webpart de Cuadro de búsqueda avanzada. Una vez allí desplegamos Ámbitos añadimos Mostrar el selector de ámbito y quitamos el tag de Mostrar el selector de idiomas, nos debe de quedar así:

Configuramos el Cuadro de búsqueda avanzada

Por si no lo has adivinado, la flecha roja significa PELIGRO, y es que deshabilitamos el tag de Mostrar el selector de tipo de resultado el webpart se rompe y solo queda eliminarlo y añadir otro igual. Bueno a lo que vamos, si sólo tocamos donde marcan las flechitas azules nos quedará el webpart parecido a este:

Cuadro de búsqueda avanzada

Si no sale a la primera habrá que refrescar la página, este webpart es un poco tontito.

Una vez que tenemos el Cuadro de búsqueda avanzada de esta forma nos vamos a definir un ámbito nuevo. Para ello nos vamos a la Administración central, a nuestro Sharepoint Services Provider favorito, que casi siempre es SharedServices1 en los servidores de pre y desde allí a Configuración de búsquedas.

Una vez aquí haremos click en Ver ámbitos:

Ver ámbitos

Allí haremos click en Nuevo ámbito, ponemos un nombre a nuestro nuevo ámbito y pulsamos aceptar. Yo para ser original lo he llamado Ámbito de Chan. Tras ésto voleremos a la ventana Ver ámbitos y ya podremos ver nuestra nueva creación. Ahora pulsamos Agregar reglas y seleccionamos el Tipo de regla de ámbito y su comportamiento:

Agregar regla de ámbito

Es importante que nos fijemos en que podemos hacer ámbitos por Dirección web, por propiedades, por Origen de contenido o seleccionando directamente todo a saco y luego con el comportamiento y sumando varias reglas a un ámbito podemos hacer selecciones bastante potentes. Yo haré una regla simple de Consulta de propiedad y requerir que el Autor sea Chan:

Configuramos regla de ámbito

Una vez que tenemos nuestro ámbito (no es mala idea compilarlo para que contenga datos) nos iremos al sitio raíz de nuestra colección de sitios y entraremos en Acciones del sitio, Modificar toda la configuración del sitio y desde allí nos vamos a Ambitos de búsqueda:

Ambitos de búsqueda en la configuración del sitio

Allí desplegaremos el Grupo de presentación: Búsqueda avanzada

Grupo de presentación

Y hacemos click en el tag de nuestro nuevo ámbito, y por último Aceptar:

Configurar grupo de presentación

Y con ésto hemos acabado. Ahora si vamos a nuestra página de búsquedas avanzadas, ¡Oh Sorpresa!

Busquedas avanzadas personalizadas

Algunos de los informadores de nuestro departamento de inteligencia de SharePoint han detectado que si el ámbito está vacío (contiene cero elementos) no se muestra, ya que MOSS es tan listo que no se molesta en hacer búsquedas en ámbitos vacíos por lo que no los muestra para total desesperación de las personas que, pese a haberlo configurado perfectamente, no tuvieron la preacución de compilar el ámbito y tras tarle mil vueltas a lo mismo terminaron por suicidarse.

Menos mal que iba a ser un post cortito...

Publicar un comentario

lunes, 20 de octubre de 2008

Busquedas en Sharepoint con SQL (III)

Y espero parar ya, qué pesado con el tema...

Hago éste post porque he estado hoy probando las búsquedas con comodines o wildcards y me he llevado algunas sorpresas. La primera es que no se pueden hacer búsquedas comodines en propiedades administradas que no devuelven datos... Se ve que se me escapa algo porque en estas propiedades se puede buscar con CONTAINS y con LIKE (sin wildcards) pero pese a poderse buscar en ellas luego no muestran nada si se cogen en el SELECT.

Me explico:


En ésta propiedad administrada (managed property) hemos introducido dos propiedades rastreadas (crawled properties) y le hemos dicho que incluya los valores de TODAS las propiedades. De este modo podemos hacer que las búsquedas por defecto sean más complejas [como en el ejemplo en el que podríamos hacer WHERE CONTAINS(ErChan,'VRG535 OR Chan')] pero luego si usamos comodines en ellas no funcionará.

En propiedades administradas que solo tengan una propiedad rastreada es donde tiene, por otro lado verdadero sentido hacer consultas del tipo WHERE Contains(NomFactura,'%RG%') aquí nos devolvería los items que tuvieran RG precedido de cualquier número de caracteres y seguido de otro cualquier número de caracteres.

Los comodines que he usado con algún tipo de éxito en SharePoint son:


  • % que sustituye a cualquier número de caracteres.

  • _ que sustituye a un solo caracter.


Uff cúantos.
Gracias al uso de éstos comodines podremos hacer también por ejemplo búsquedas como WHERE CONTAINS(NomFactura,'_RG%')

Se me olvidó decir el otro día que también podemos usar cosas como WHERE CONTAINS(NomFactura,'Hola') AND NOT CONTAINS (Estado,'PAGADO').

Y con ésto he profundizado en el tema bastante más de lo que yo mismo creía que llegaría a profundizar. De todas formas, si llego a enterarme de algo interesante postearé más todavía.

Saludos a Portugal.
Publicar un comentario

jueves, 16 de octubre de 2008

Busquedas en Sharepoint con SQL (II)

Hoy mismo lo voy a continuar, qué ilusión que te lean desde Bulgaria, dentro de nada tendré un ego tan grande como el de Jay de TC, bueno, a lo que vamos...
Como iba diciendo ayer en el post
Busquedas en Sharepoint con SQL (I) es muy fácil hacer consultas al motor de búsquedas de MOSS, lo malo es saber qué preguntarle.
Es interesante a la hora de hacer un buscador custom poder buscar por los campos que en cada caso nos interesen, y no con el freetext.
Out of the box se pueden hacer consultas del tipo:
"SELECT Title FROM SCOPE() WHERE CONTAINS(Title,'Chan')"
De esta forma nos devolverá una tabla con todos los elementos de lista o biblioteca cuyo Title sea 'Chan'. Y quien dice title dice una de las ciento y pico managed properties (Asignaciones de propiedades de metadatos) que hay por defecto en MOSS, solo con esto ya podemos ofrecer alguna potencia, por ejemplo:
"SELECT Title FROM SCOPE() WHERE CONTAINS(Title,'Chan') AND Size > 162 ORDER BY Created"
Pero aún así no es suficiente, por eso mismo SharePoint nos permite crear nuestras propias managed properties para poder buscar en cualquiera de las columnas que hayamos creado en nuestro portal.


luego


Desde allí hacemos click en Nueva propiedad administrada y configuramos nuestra columna para buscar:

Por último, para rellenar de datos nuestra propiedad administrada necesitaremos hacer un rastreo completo (Full Crawl).
He creado una columna llamada factura y le he asignado la propiedad rastrada (crawled property) Factura(Texto).
Las crawled properties salen después de crear una columna en una lista cualquiera del portal y hacer un rastreo completo, o sea, que puedes buscar por el parámetro que te de la gana.

Después de tener todos los campos que necesitamos ya sí que podemos hacer búsquedas potentes, por ejemplo:
"SELECT Title, Factura, FechaFactura FROM SCOPE() WHERE CONTAINS(Factura,'VRG535') ORDER BY FechaFactura"
O por ejemplo si necesitamos más de una palabra en el CONTAINS:
"SELECT NombreReunion, Asistentes FROM SCOPE() WHERE CONTAINS(Asistentes,'Chan AND Jay') ORDER BY FechaReunion"
O bien:
"SELECT NombreReunion, Asistentes FROM SCOPE() WHERE CONTAINS(Asistentes,'Chan AND Jay') AND CONTAINS(Supervisor,'Eva') ORDER BY FechaReunion"
Si quieres buscar en un scope (ámbito) específico puedes hacer:
"SELECT NombreReunion, Asistentes FROM SCOPE() WHERE "SCOPE"='MiScope' AND CONTAINS(Asistentes,'Chan') AND NOT CONTAINS(Supervisor,'Eva OR Jay') ORDER BY FechaReunion"
Y solo con ésto ya me siento capaz de bastantes cosas...
¡¡YOOOOOO TENGO EL PODER!!

También funciona el Like e incluso algunos wildcards o comodines, algún día de éstos si llego a enterarme de cómo funcionan lo postearé, mientras tanto prueba a discreción y disfruta por fin de unas búsquedas relativamente potentes.
Publicar un comentario

miércoles, 15 de octubre de 2008

Busquedas en Sharepoint con SQL (I)

Además es bastante fácil hacerlas, quizá lo malo sea saber qúe preguntar a SharePoint y cómo. Para empezar tenemos que agregar a nuestro proyecto la librería:
using Microsoft.Office.Server.Search.Query;

Si, esa, la que cuesta dinero. Y luego pegamos esta función:
public static DataTable resultadosSqlQuery(string query, SPWeb web)
{

FullTextSqlQuery sqlQuery = new FullTextSqlQuery(web.Site);
sqlQuery.RowLimit = 50000;
//50000 deben ser suficientes, ?no?
sqlQuery.KeywordInclusion = KeywordInclusion.AllKeywords;
sqlQuery.TrimDuplicates =
true;
sqlQuery.ResultTypes =
ResultType.RelevantResults;
sqlQuery.QueryText = query;
ResultTableCollection tablasResultados = sqlQuery.Execute();
ResultTable resultadosRelevantes = tablasResultados[ResultType.RelevantResults];

DataTable resultados = new DataTable();
resultados.Load(resultadosRelevantes);

return resultados;
}

Así de fácil. Con ésto ya podrás hacer querys a diestro y siniestro, del tipo:
"SELECT Title FROM SCOPE() WHERE FREETEXT('Chan')"

Por supuesto falta bastante para que este post sea todo lo interesante que puede ser, pero hoy no tengo tiempo y con esto ya podéis probar asi que me voy, prometo continuarlo en breve.
Publicar un comentario

lunes, 13 de octubre de 2008

¿Es mejor usar URL de producción en el servidor de preproducción?

Pues yo creo que si.

¿Cuántas veces no pasa que los links funcionan perfectamente en tu servidor de pre, pero luego al pasarlo a pro se te rompe alguno (por no decir la mitad)?

Hacer esto es bastante fácil y, normalmente, te quita un montón de quebraderos de cabeza.

Simplemente hay que ir al fichero hosts, que está en C:\windows\system32\drivers\etc\hosts , es así, sin extensión ni nada, abrirlo con el mejor editor, el block de notas y añadir al final la IP local junto con la URL de nuestro portal de producción.

127.0.0.1       localhost
127.0.0.1 http://www.spenta.es
127.0.0.1 www.spenta.es #Asi no hay duda

Tras guardar los cambios, las peticiones que se hagan a http://www.spenta.es/ desde el servidor se enrutarán a 127.0.0.1. Si no te fías haz un ping a http://www.spenta.es/.

Una vez hecho esto deberemos de añadir la ruta de acceso alternativo a nuestro servidor, de esta forma:


Una vez en la lista de Asignaciones de acceso alternativas pulsamos y luego cambiamos a la aplicación web que nos corresponda para el sitio del desarrollo aquí .


Tras esto añadimos el nuevo mapeo de URL a la Predeterminada, por ejemplo:

Pulsamos Guardar y listo, ya podemos llamar a la URL de producción desde el portal de pre.

Si queremos ser muy puristas podemos cambiar el hosts antes de instalar nada en el portal y luego hacer todas las instalaciones de MOSS y SQL llamando a la URL de producción. De esta forma el pobre portal de PRE nunca sabrá que no es el verdadero protagonista.

Hay veces que da problemas porque el navegador no se cosca bien y no te reconoce la URL, si te pasa ésto prueba a reparar la conexión de red, a borrar las cookies, reiniciar, volver a configurar el alternate access mapping, hacer iis reset, esperarte un ratitlo... no sé, échale imaginación.



Aunque haya elegido la url de la página de spenta yo no he sido el que la ha hecho, que conste.
Publicar un comentario

miércoles, 8 de octubre de 2008

Intentando borrar elementos de lista rápidamente

Actualmente estoy importando grandes cantidades de datos a listas de SharePoint, y (como muchas veces meto la pata) se me ha planteado la necesidad de borrarlos.

Empecé haciendo esto:

public static void limpiaLista(SPList lista)
{
while
(lista.Items.Count > 0)
lista.Items[0].Delete();
}
Y efectivamente, de esta forma terminas por borrar los elementos, pero cuando hay más de 2000 empiezas a notar que tarda. Entonces me puse a investigar y leí que era por culpa del modelo de objetos. Solución: Nos saltamos el modelo de objetos con comandos CAML.

Tras otro rato de investigación cambié mi procedimiento por:
public static void limpiaListaRapido(SPList lista)

{

List<int> items = new List<int
>();

foreach (SPListItem item in
lista.Items)

items.Add(item.ID);

// Creamos el batch CAML

string batch = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+

"<Batch>"
+

"<Method>"
+

"<SetList Scope=\"Request\">" + lista.ID + "</SetList>"
+

"<SetVar Name=\"ID\">{0}</SetVar>"
+

"<SetVar Name=\"Cmd\">Delete</SetVar>"
+

"</Method>"
+

"</Batch>"
;



// Y ahora para cada objeto de la lista aplicamos el comando

foreach (object item in
items)

lista.ParentWeb.ProcessBatchData(
string
.Format(batch, item));

}


Y probé, y era más rápido, de hecho bastante más rápido, pero tenía un problema, que no solo borraba los elementos de la lista sino que, además, los metía en la papelera de reciclaje, con lo cual tras hacer el "limpiaListaRapido", si no quieres esperar 60 días a que te desaparezcan los datos basura tienes que hacer esto:


public static void vaciaPapeleras(SPWeb web)
{
//Vaciamos la papelera del sitio
web.RecycleBin.DeleteAll();
//Vaciamos la papelera de la coleccide sitios
web.Site.RecycleBin.DeleteAll();
}


Y resulta que vaciar las dos papeleras de reciclaje tarda otro buen rato por lo que en resumen:

El tiempo que tarda "limpiaLista" es comparable al tiempo que tarda "limpiaListaRapido"+"vaciaPapeleras".

Eso sí, si no te importa que la papelera se te llene de basura (que bien mirado para eso esta), el método de las CAML es bastante más rápido.

Ahora, la pregunta que me surge es otra, ¿Hay un comando CAML que borre las entradas sin pasar por la papelera? Si lo encuentro lo postearé (suponiendo que lo busque).
Publicar un comentario

martes, 7 de octubre de 2008

Mapeo de caracteres “extraños” al Hex interno de SharePoint

<edit>Solución más completa al tema</edit>

Hay veces que hace falta usar los nombres internos de los campos. Cuando se trata de un espacio (_x0020_) lo hemos visto mil veces, pero ¿Y una ü con su diéresis? voy a hacer una breve inciso castellano para continuar el trabajo empezado en este post http://abstractspaces.wordpress.com/2008/05/07/sharepoint-column-names-internal-name-mappings-for-non-alphabet/#comment-82.


Como es natural al compañero de AbstractSpaces le daba un poco igual el tema de los caracteres especiales que se usan en nuestra lengua, pero a mi me hicieron falta.
Por si acaso los necesita alguien o yo mismo alguna otra vez aquí van, de esa forma nos ahorramos el ratito de sacarlos:

CharacterInternal Hex CodeCaracterCódigo Hex
~_x007e_á_x00e1_
!_x0021_Á_x00c1_
@_x0040_é_x00e9_
#_x0023_É_x00c9_
$_x0024_í_x00ed_
%_x0025_Í_x00cd_
^_x005e_ó_x00f3_
&_x0026_Ó_x00d3_
*_x002a_ú_x00fa_
(_x0028_Ú_x00da_
)_x0029_ü_x00fc_
__ñ_x00f1_
+_x002b_Ñ_x00d1_
-_x002d_
=_x003d_
{_x007b_
}_x007d_
:_x003a_
_x0022_
_x007c_
;_x003b_
_x0027_
\_x005c_
<_x003c_
>_x003e_
?_x003f_
,_x002c_
._x002e_
/_x002f_
`_x0060_
_x0020_
Vaya, la suya es más larga…
Publicar un comentario

sábado, 4 de octubre de 2008

Jugando con las bases de datos de contenido de SharePoint

¿Hay alguien que no tenga a estas alturas experiencia con atachar y desatachar (¿Asociar y desasociar en castellano?) bases de datos de contenido del SharePoint? Sí hay alguien, de hecho hay mucha gente.
Gracias a esto es fácil hacer backups y restores con las herramientas de SQL, mover las bases de datos a otros servidores, por ejemplo para ampliar granjas, guardar los datos en una cinta y olvidarte de ellos hasta el día que te hagan falta y todos los procesos que se te ocurran con bases de datos con tranquilidad fiabilidad y en cuestión de segundos (quizá más de 60, o más de 86400 segundos si las bases de datos son realmente gordas).
¿Que pasa si la base de datos de contenido de tu SharePoint crece tanto que no cabe en el disco duro que la alberga? pues que nos compramos un disco duro más gordo y la movemos a el.
Por ejemplo, el caso más extremo que se me ocurre es desplegar una base de datos en una granja diferente y ¿quién dijo miedo? es el que intentaré reflejar en este post (lo malo es que en mi casa solo tengo una VM, pero bueno intentaré simularlo lo mejor posible).
Lo primero que necesitamos es tener instalado el SQL Server Management Studio. Si tienes el el SQL Server Express te lo tendrás que descargar de aquí y si instalaste una versión de pago es posible que ya lo tengas instalado o bien que tengas que ir a por tu DVD de instalación del SQL Server e instalar las herramientas.
Lo segundo es que ambas granjas tengan la misma versión, ya puestos la última (SP1). Ya sabes, instalamos WSS 3.0 SP1 primero y luego MOSS 2007 SP1.
Y yo creo que con esto es suficiente, arremangarse niñio.
1.- ¿Cuales son mis bases de datos de contenido?
Antes de empezar a hacer el trasvase tenemos que saber cómo se llaman las bases de datos que queremos trasvasar. Para ello abrimos la administración central y desde allí --> Administración de aplicaciones y luego Bases de datos de contenido.
Bases de datos de contenido
Como seguramente, por defecto te tomará cualquier aplicación web menos la que tu quieres cambiaremos la aplicación web:
cambiar aplicación web
Y una vez que hayamos seleccionado la aplicación web buena podremos ver la lista de bases de datos de contenido que la nutren. En mi caso y muy convenientemente solo es una, la archiconocida por todos WSS_Content.
(Un breve inciso: A mi entender, la única explicación plausible para tener más de una base de datos de contenido por aplicación web es porque, en caso de catástrofe, es más rápido restaurar una base de datos pequeña que una grande, pero NO PASA ABSOLUTAMENTE NADA POR TENER CONTENT DATABASES TAN GRANDES COMO QUERÁIS, Microsoft no pone límite y yo he trabajado con bases de datos de 500GB sin ningún problema de rendimiento.)
Ahora ya sabemos qué queremos copiar, así que vamos con el siguiente paso.
2.- Hacemos backup de nuestra base de datos:
Para ello nos vamos al SQL Server Management Studio y…
backup
Tras pulsar backup debemos configurar la copia en la ventanita que nos sale a continuación. No tiene demasiado misterio, solo hay que recordar que existen los backups diferenciales y que es mejor guardar la copia en un sitio que conozcamos.
configBackup(Otro breve inciso: Como habrás imaginado no es la mejor idea del mundo hacer este proceso en el momento de mayor actividad del servidor, aunque se puede hacer en ese momento si te gusta el riesgo)
3.- Nos llevamos la BD al servidor nuevo
Como tenemos una memoria excelente y nos acordamos de dónde hemos guardado el ficherito .bak pues nos vamos allí y lo pasamos al otro server. Dicen las malas lenguas que el SQL Server 2008 comprime los backups, yo no lo he probado todavía, pero si estoy seguro de una cosa el 2005 no lo hace, así que si vas a pasar la base de datos por internet a alguien es una buena idea comprimirla.
4.- Restauramos la base de datos en el servidor nuevo
Algunas veces cuesta un poco de trabajo esto de restaurar las bases de datos.


restore

configRestore
Si en el servidor donde vais a hacer la restauración de la base de datos ya hay una base de datos con el mismo nombre que la que vais a restaurar y además está en uso el SQL os va a decir que no puede tener acceso exclusivo a ella y va a fallar. Esto es normal, una cosa es hacer el backup en caliente y otra es restaurar una copia de seguridad en caliente.
En ese caso, antes del restore, haremos un detach (Desasociar en castellano) de la base de datos marcando la casilla de Drop Connections (¿Cerrar conexiones?) así:
detach configDetach
Si todavía os falla será porque necesita sobreescribir la base de datos antigua, id a Options en la ventana de configuración del restore y dadle permiso al pobrecito.configDetachOptions
5.- Configurando la aplicación web para que use nuestra flamante base de datos de contenido:
Igual que en el paso uno, pero esta vez en el servidor nuevo, Abrimos la administración central y desde allí --> Administración de aplicaciones y luego Bases de datos de contenido, después cambiaremos la aplicación web a la que nos convenga.
Una vez hecho esto tendremos que quitar la base de datos de contenido que tiene la aplicación, pulsamos sobre ella y en la ventana que nos sale marcaremos “Quitar base de datos de contenido” luego Aceptar y Aceptar.
quitarContentDB
Y luego:



agregarContentDB agregarContentDBConfig
(Si la tienes demasiado grande SharePoint se asustará al verla y habrá que metérsela por la puerta trasera) Si la base de datos que estamos adjuntando a nuestra aplicación web es demasiado grande nos dará un error, no pasa nada, para las cosas serias siempre podemos usar el socorrido stsadm el comando sería más o menos:
stsadm -o addcontentdb -url http://erChan -databasename wss_content
6.- Abrimos la web y listo…
Si todo ha ido bien ya podríamos entrar en nuestra aplicación web con su recién atachada base de datos, pero es posible que si has cambiado de entorno el usuario administrador ya no sea el mismo… En este caso tendrías que ir a Administración central –> Administración de aplicaciones –> Directiva de aplicación Web y meter allí como control total al administrador de esta granja.
directiva
Y fin, qué post más largo. Ya paso de comentar más nada ¡UF!.
Hay quien dice que este método solo funciona si mientras esperas lees un libro de yoga, pero no creo yo que sea para tanto, de hecho creo que el post en sí ya es un libro de yoga.
Publicar un comentario

Cross-Site Lookup Columns out-of-the-box (más o menos)

Cuántas veces he necesitado una columna de búsqueda que lea desde una lista que pertenece a otro sitio ... y a veces lo sigo necesitando.

Qué fácil sería todo si se le pudiese decir a las columnas que buscasen en cualquier sitio del portal, pero no se puede. No pido tanto, no, me conformaría con menos, ¿no sería posible hacer algún apaño? Bueno, algo sí que podemos hacer.

Quizás no podamos hacer lookup desde y hasta cualquier parte del portal, pero si que podemos hacer lookup desde sitios hijos hasta sitios padres. El truco es:

1.- Nos vamos al sitio Padre y allí creamos una columna de sitio. No vale cualquiera, tiene que ser una columna de sitio tipo lookup. La parte mala es que SharePoint solo te permitirá elegir entre columnas del sitio en el que estás creando la columna de sitio.

columnas ... crear ... columnaBusqueda

2.- Cuando hayamos creado la columna de búsqueda en el sitio raíz nos será posible heredarla desde cualquier lista de cualquier sitio hijo.

CrearColumna ...AgregarColumna

3.- Y una vez integrado en nuestra lista el resultado será como este:

ResultadoEjemplo

4.- Y ya que hemos conseguido esto, ¿no sería bonito tener una lista donde viésemos nuestros documentos relacionados con anuncios? Pues sería tan fácil como crear una vista y agrupar por nuestra "Cross-Children-Site Lookup Column" (hay que ver los nombres que me invento), y quedaría así:

listaAgrupada

Qué bien cuando las cosas funcionan bien, y sin programar, ¿Quién da más?

Publicar un comentario