Lancement rapide

 

 À propos de ce blog

 
À propos de ce blog
Bonjour,
Je suis VANNESTE Xavier, développeur depuis 10 ans sur les technologies microsoft, depuis 2002 sur la plateforme .NET et depuis 2003 sur SharePoint.
Ce site me permet de partager mes connaissances sur l'architecture, sur .Net et sur SharePoint.

Accueil
CPL-logo.png
mars 27
[SharePoint 2010] La Core Result WebPart Votre meilleur source d’informations

Introduction

Lorsqu'on parle de la Core Result Web Part ou la webpart de résultat de recherche, la première chose qui vient en tête c'est la webpart qui se trouve dans le centre de recherche SharePoint et qui affiche le résultat de recherche. Elle est assez rarement utilisée, voire jamais, ailleurs que dans le centre de recherche. Cependant elle peut véritablement servir à beaucoup plus qu'afficher juste le résultat de la recherche dans le centre de recherche.

Imaginez que vous vouliez afficher les derniers documents du site, les documents écris par telle personne mais aussi pouvoir filtrer par site, afficher que les PDF ou les documents Word ? Qu'allez-vous faire ? En discutant avec des développeurs SharePoint la première chose qui vient en tête c'est une requête CAML avec l'utilisation de la classe SPSiteDataQuery. Etes-vous sûr qu'il faille développer quelque chose ? On le verra il y a beaucoup plus simple.

Mise en place

Commençons par le début, on va créer une page qui accueillera notre recherche d'information, pour cela on va sur « Site Actions » à « More option » à « Web Part Page » :

Et on clique sur Create, pour l'exemple on va appeler notre page VerticalSearch avec le layout « Header, Left Column, Body » et notre page dans Site Pages:

On va ajouter les Core Result WebPart dans les trois zones :

Maintenant on peut les paramétrer et afficher les informations sur une page.

Quelques cas concret

Les documents du mois

La première chose que je souhaite c'est avoir tous les documents qui ont été écris ce mois-ci. Pour cela si je suis dans le centre de recherche je peux taper [write="this month"]

Cela est intéressant mais ce que je veux c'est uniquement les documents, soit la Managed Property IsDocument avec la valeur true :

J'ai cependant encore des parasites dans mon résultat, en effet les pages ne m'intéresse pas du tout et encore moins la page que j'ai créé pour l'exemple, il suffit d'enlever l'extension « aspx » de mon résultat :

Voilà maintenant dans mon résultat j'ai mes deux documents créent ce mois-ci et pas les pages du site. Mais ce qui m'intéresse c'est de les mettre dans ma page VerticalSearch. Pour cela je customise ma page (Site ActionàEdit page) et sur la webpart de la zone body je clique sur « Edit Web Part » :

Le but ici est de mettre la query quelque en prédéfinie dans la webpart. C'est le rôle de la propriété « Fixed Keyword Query » qui est dans la zone Result Query Option :

J'entre donc ma requête précédemment faite :

Et voila le résultat :

Après avoir mis le titre et changer le chrome type :

 

 

Les évènements

Je souhaite ajouter une vue sur les évènements inscrits dans le site. Pour cela je vais demander tous les items dont le Content Type est équivalent à event soit [contenttype= « event »]

Si j'ajoute comme je l'ai fait la query a ma webpart dans la zone Left Column :

Voici ce que j'obtiens :

Les deux webparts ont changé, en fait il faut cloisonner les requêtes des webparts sinon le QueryManager transmettra la même information de résultat à toutes les webparts. On va changer le Cross-Web Part query ID en Query2 :

Le résultat escompté est maintenant atteint :

On pourrait les trier par date :

Ici le résultat par page sera le nombre maximum d'items qui apparaitront car la webpart de paginations n'a pas été mise.

Comme on a accés a toutes les managed properties on peut récupérer les liste vide par exemple :

Ou alors tous les fichiers qui sont superieur a 1mb (soit 1048576 octets)

Si on ajoute cela a notre page en Query 3 et qu'on change l'affichage:

Voici le résultat :

On pourrait aussi modifier le XSLT qui fait le rendu du résultat de recherche pour personnaliser encore plus l'affichage.

Référence

http://msdn.microsoft.com/en-us/library/hh644280(v=office.14).aspx

mars 09
[Techdays 2012] WebCast de ma session au techdays

Retrouvez le webcast de ma session au techdays, mais aussi toutes les sessions des techdays sur :

http://www.microsoft.com/fr-fr/showcase/details.aspx?uuid=4d6176b3-fff7-481e-8c81-971b23c0964f

février 05
[Techdays 2012]Retrouvez moi avec Nicolas Schmitt et Geoffrey Lalanne

Une personne passe encore en moyenne 8 heures par semaine à chercher une information (http://www.amplexor.com/ecm-bulletin/ecm-articles/enterprise-search-where-do-we-go-here). Un moteur de recherche d'entreprise, dit "à facettes", fait bien plus qu'un simple moteur de recherche Web, car vos besoins sont spécifiques : taxonomie, folksonomie, sécurité, intégration à la GED, social search et interopérabilité. Venez découvrir ce qu'un vrai moteur de recherche d'entreprise peut faire pour vous, en accroissant votre productivité au quotidien, à travers 5 cas d'usages déployés chez nos clients : jusqu'où pourrez-vous aller grâce à Fast for SharePoint 2010?

Jeudi 9 février de 11h00 a 12h00.

http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx#SessionID=62191f19-06e3-4093-90a6-2e5f7ffa0264

février 01
[SharePoint 2010] BCS Partie 6: Visual Studio 2010 et le Streamer (StreamAccessor)

Introduction

Jusque maintenant on ne peut pas dire que ce qu'on a fait avec Visual Studio soit simple, et on ne peut pas dire qu'on ait un résultat plus probant qu'avec SharePoint Designer.

Jusque maintenant aussi, on ne peut pas dire qu'on ait autre chose qu'une liste, alors que la plupart du temps on utilise les library dans SharePoint, dans lequel des documents sont stockés.

Dans notre exemple on indexe une GED, hors on n'a pas encore remonté les documents. C'est le but du StreamAccessor.

Dans cet article on verra comment remonter les documents stockés dans notre base de données.

Avec Rise les documents sont stockés directement dans la base de données on va donc apporter quelque modification au code pour utiliser ReadItem afin de récupérer le contenu des documents, ensuite nous créerons notre Method Instance StreamAccessor.

Le BCS Designer

On ajoute une méthode à l'entité RiseDocument dans le BCS Designer :

On ajoute deux paramètres, DocID et returnParameter, DocID est de direction in et returnParameter est de direction Return, le type descriptor sera DocIDTypeDescriptor et DocRise:

Les Paramètres pour DocIDTypeDescriptor sont

Le type correspond au type de l'identifier DocID.

Pour DocRise les paramétres vont être un peu plus complexe, on reprendra l'entité DocRise de ReadItem auquel on va ajouter Content de Type System.IO.Stream :

Maintenant on a les fondations pour notre BDC, il nous reste à ajouter notre méthode instance de type StreamAccessor :

Le return parameter name sera le typedescriptor returnParameter qui contient toutes les informations de RiseDocument, mais le return type descriptor sera content car c'est cette propriété qui contient le contenu qui doit être retourné.

Si on en reste là, le téléchargement ne sera pas terrible car il y'aura pas de nom de fichier, pas d'extension et pas de mimetype.

Pour cela on doit rajouter le lien vers les propriétés titre et mimetype du fichier. Dans les custom properties de la méthode instance on ajoute :

MimeTypeField prend en valeur le nom du type descriptor qui contient le nom du fichier, et FileNameField contient le nom du document qui sera téléchargé.

Suite à ces changements le Service a été modifié et il nous reste à mettre le code dans notre assemblie .net

Changement du code

On va changer le code de RiseDocument, afin de refléter le retour du contenu.

Pour cela on va ajouter une propriété de type Stream s'appelant Content :

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// This class contains the properties for Entity1. The properties keep the data for Entity1.

/// If you want to rename the class, don't forget to rename the entity in the model xml as well.

/// </summary>

public partial class RiseDocument

{

//TODO: Implement additional properties here. The property Message is just a sample how a property could look like.

public long DocID { get; set; }

public string MimeType { get; set; }

public string Title { get; set; }

public string Description { get; set; }

public string Langue { get; set; }

public Stream Content { get; set; }

}

}

 

 

Maintenant on va modifier le Service RiseDocumentService pour remplir la propriété Content :

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.SqlClient;

using System.Data;

using System.IO;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// All the methods for retrieving, updating and deleting data are implemented in this class file.

/// The samples below show the finder and specific finder method for Entity1.

/// </summary>

public class RiseDocumentService

{

/// <summary>

/// This is a sample specific finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <param name="id"></param>

/// <returns>Entity1</returns>

///

 

 

private static SqlConnection getSQLConnection()

{

SqlConnection _cnData;

_cnData = new SqlConnection("Data Source=srvsql; Initial Catalog=CMSRise;User ID=SA; Password=P@ssw0rd;");

_cnData.Open();

return _cnData;

}

public static RiseDocument ReadItem(long docID)

{

RiseDocument rd = new RiseDocument();

MemoryStream ms = new MemoryStream();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content " +

"where t_cms_u_Document.c_id=@docID";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

if (drData.Read())

{

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

byte[] bContent = (byte[])drData.GetValue(2);

 

ms.Write(bContent, 0, bContent.Length);

ms.Flush();

ms.Position = 0;

rd.Content = ms;

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

}

else

{

rd.DocID = -1;

rd.MimeType = "";

rd.Content = null;

rd.Title = "";

rd.Description = "";

rd.Langue = "";

 

}

 

 

}

}

return rd;

}

/// <summary>

/// This is a sample finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <returns>IEnumerable of Entities</returns>

public static IEnumerable<RiseDocument> ReadList()

{

List<RiseDocument> rds = new List<RiseDocument>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content ";

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseDocument rd = new RiseDocument();

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

rds.Add(rd);

}

 

}

}

return rds;

}

 

public static IEnumerable<RiseSite> RiseDocumentToSite(long docID)

{

List<RiseSite> lstRs = new List<RiseSite>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Site.c_id, t_cms_u_Site.c_u_Name "+

"FROM t_cms_u_Content INNER JOIN "+

"t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content INNER JOIN "+

"t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id WHERE (t_cms_u_Document.c_id = @docID) ";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseSite rs = new RiseSite();

rs.SiteID = (int)drData.GetInt64(0);

rs.SiteName = drData.GetString(1);

lstRs.Add(rs);

}

 

}

}

return lstRs;

}

 

public static Stream GetContentForDocID(long DocID)

{

return ReadItem(DocID).Content;

}

 

}

}

 

 

On a ajouté une méthode GetDocumentForDocID qui retournera le stream pour le StreamAccessor et on a modifié ReadItem pour remplir la propriété Content.

Cependant on a vu que le Mimetype et le nom du document est important aussi pour le download du document toutes les propriétés doivent donc être remplis.

 

Le résultat

Le résultat est le suivant :

Le lien Click here to download est créé automatiquement si on clique dessus il récupére le nom du fichier et le mimetype et revoit le fichier stocké dans la base de données :

Si on clique sur open le document s'ouvre automatiquement.

Maintenant on obtient quelque chose de plus proche de ce que SharePoint peut faire.

Avec la webpart Business Data list on obtient ce qui se rapproche le plus d'une document library :

janvier 25
[SharePoint 2010] BCS Partie 5: Visual Studio 2010 les associations

Série D'articles:

Introduction

Comme on a vu avec SharePoint designer on peut faire les associations entre les entités de votre BCS afin de mettre en place des vues Master/Details sur des associations. On va reprendre la création de notre BCS fait avec Visual Studio, on va lui ajouter une entité Site et on va faire les changements permettant de l'exploiter, on verra que suite à ces changements, on aura le même comportement qu'avec SharePoint Designer, pour l'instant on recherche le même comportement on verra par la suite les avantages à utiliser Visual Studio.

Avant de continuer on va se pencher sur la description de méthode et de méthode instance :

Modification de l'existant 

Premièrement on va supprimer le type descriptor « Site » dans le BDC Explorer.

Puis on va modifier le code des classes pour ne plus retourner « Site » :

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// This class contains the properties for Entity1. The properties keep the data for Entity1.

/// If you want to rename the class, don't forget to rename the entity in the model xml as well.

/// </summary>

public partial class RiseDocument

{

//TODO: Implement additional properties here. The property Message is just a sample how a property could look like.

public long DocID { get; set; }

public string MimeType { get; set; }

public string Title { get; set; }

public string Description { get; set; }

public string Langue { get; set; }

public byte[] Content { get; set; }

}

}

 

 

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.SqlClient;

using System.Data;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// All the methods for retrieving, updating and deleting data are implemented in this class file.

/// The samples below show the finder and specific finder method for Entity1.

/// </summary>

public class RiseDocumentService

{

/// <summary>

/// This is a sample specific finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <param name="id"></param>

/// <returns>Entity1</returns>

///

 

 

private static SqlConnection getSQLConnection()

{

SqlConnection _cnData;

_cnData = new SqlConnection("Data Source=srvsql; Initial Catalog=CMSRise;User ID=SA; Password=P@ssw0rd;");

_cnData.Open();

return _cnData;

}

public static RiseDocument ReadItem(long docID)

{

RiseDocument rd = new RiseDocument();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content " +

"where t_cms_u_Document.c_id=@docID";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

if (drData.Read())

{

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Content = (byte[])drData.GetValue(2);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

}

else

{

rd.DocID = -1;

rd.MimeType = "";

rd.Content = null;

rd.Title = "";

rd.Description = "";

rd.Langue = "";

 

}

 

 

}

}

return rd;

}

/// <summary>

/// This is a sample finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <returns>IEnumerable of Entities</returns>

public static IEnumerable<RiseDocument> ReadList()

{

List<RiseDocument> rds = new List<RiseDocument>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content ";

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseDocument rd = new RiseDocument();

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Content = (byte[])drData.GetValue(2);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

rds.Add(rd);

}

 

}

}

return rds;

}

 

}

}

 

 

Maintenant on peut passer à la création de notre entité <Site>

Création de nouvelles entités

On va commencer par le BCS designer :

On va nommer l'entité Site puis on va mettre un nouvelle identifier SiteID :

Sans oublier de mettre le bon type pour SiteID :

 

On ajoute les deux méthodes ReadList et ReadItem

Pour nous aider a designer les méthodes on utilisera le BDC Method Detail :

On va créer les paramètres pour ReadList :

Voici le contenu, on change le nom du type descriptor et la direction en Return :

Maintenant on va créer notre List Instance

Une Méthode instance permet de spécifier quand utiliser la méthode (retour de l'ensemble des entités, d'une seule entité, mise a jours d'une entité, suppression d'une entité…….)

 

On specifie le return parameter :

On va faire de même avec ReadItem :

On spécifie le return parameter :

 

Si l'on regarde dans le solution explorer on se rend compte qu'on n'a pas le site entity mais que le SiteService, on va donc créer la classe Site.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BDCRiseCMS.BdcModel1

{

public class RiseSite

{

public int SiteID { get; set; }

public String SiteName { get; set; }

}

}

 

 

Maintenant qu'on l'a créé on peut terminer le schema de notre BCS, dans le BDC explorer on va changer le type des type descriptor SiteRise et SiteRiseList :

Pour SiteRiseList on coche en plus is Enumerable :

SiteID :

 

On finit l'entité SiteRise :

SiteService a été généré par le designer :

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace BDCRiseCMS.BdcModel1

{

public partial class SiteService

{

public static IEnumerable<RiseSite> ReadList()

{

throw new System.NotImplementedException();

}

 

public static RiseSite ReadItem(int ID)

{

throw new System.NotImplementedException();

}

}

}

 

 

Avec le code :

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.SqlClient;

namespace BDCRiseCMS.BdcModel1

{

public partial class SiteService

{

private static SqlConnection getSQLConnection()

{

SqlConnection _cnData;

_cnData = new SqlConnection("Data Source=srvsql; Initial Catalog=CMSRise;User ID=SA; Password=P@ssw0rd;");

_cnData.Open();

return _cnData;

}

 

public static IEnumerable<RiseSite> ReadList()

{

List<RiseSite> lstRS = new List<RiseSite>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT c_id, c_u_Name FROM t_cms_u_Site" ;

 

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseSite rs=new RiseSite();

rs.SiteID = (int)drData.GetInt64(0);

rs.SiteName = drData.GetString(1);

lstRS.Add(rs);

}

}

}

return lstRS;

}

 

public static RiseSite ReadItem(int ID)

{

RiseSite rs = new RiseSite();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT c_id, c_u_Name FROM t_cms_u_Site " +

"where c_id=@ID";

cmdata.Parameters.AddWithValue("@ID", ID);

SqlDataReader drData = cmdata.ExecuteReader();

if (drData.Read())

{

rs.SiteID = drData.GetInt32(0);

rs.SiteName = drData.GetString(1);

}

else

{

rs.SiteID = -1;

rs.SiteName = "";

}

 

}

}

return rs;

}

}

}

 

Le résultat une fois la profile page terminé :

 

 

Mise en place de l'association

Très bien maintenant passons au plus simple, on va créer une association entre les deux entités, cette association générera une méthode dans chaque entité permettant de faire une vue Master/Details.

On ne remplit rien d'autre, seul le code sera à modifier :

Code dans SIteService

public static IEnumerable<RiseDocument> SiteToRiseDocument(int siteID)

{

List<RiseDocument> rds = new List<RiseDocument>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN " +

"t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content INNER JOIN " +

"t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id WHERE (t_cms_u_Site.c_id = @siteID) ";

cmdata.Parameters.AddWithValue("@siteID", siteID);

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseDocument rd = new RiseDocument();

if(!drData.IsDBNull(0))

rd.DocID = drData.GetInt64(0);

if (!drData.IsDBNull(1))

rd.MimeType = drData.GetString(1);

if (!drData.IsDBNull(2))

rd.Content = (byte[])drData.GetValue(2);

if (!drData.IsDBNull(3))

rd.Title = drData.GetString(3);

if (!drData.IsDBNull(4))

rd.Description = drData.GetString(4);

if (!drData.IsDBNull(5))

rd.Langue = drData.GetString(5);

rds.Add(rd);

}

 

}

}

return rds;

 

}

 

 

Code dans RiseDocumentServices :

public static IEnumerable<RiseSite> RiseDocumentToSite(long docID)

{

List<RiseSite> lstRs = new List<RiseSite>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Site.c_id, t_cms_u_Site.c_u_Name "+

"FROM t_cms_u_Content INNER JOIN "+

"t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content INNER JOIN "+

"t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id WHERE (t_cms_u_Document.c_id = @docID) ";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseSite rs = new RiseSite();

rs.SiteID = (int)drData.GetInt64(0);

rs.SiteName = drData.GetString(1);

lstRs.Add(rs);

}

 

}

}

return lstRs;

}

 

 

Le résultat est le suivant :

Le master detail est bien en place. On a donc le même comportement qu'avec SharePoint Designer.

Résultat

Le résultat est proche de SharePoint designer, même si actuellement il est impossible d'indexer ce BCS. Ici on se rend compte que faire la même chose que SharePoint Designer n'est pas si simple avec Visual Studio, cependant à partir de maintenant les possibilités réélles de Visual Studio vont être utilisées.

1 - 5Suivante