Ignorer les commandes du Ruban
Passer au contenu principal

Lancement rapide

Accueil
CPL-logo.png
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.

janvier 18
[SharePoint 2010] BCS Partie 4: Visual Studio 2010

Série D'articles:

Introduction

J'ai beaucoup utilisé les BDC dans SharePoint 2007, il est clair que l'édition de fichiers XML était loin d'être la chose que j'appréciais le plus. Lorsque j'ai abordé les BCS avec SharePoint 2010 (pendant des BDC de SharePoint 2007) j'ai été ravi de voir qu'un éditeur BCS était présent dans Visual Studio. Puis ma joie a fait place à la déception. En effet il ne faut pas vous attendre à un éditeur qui fasse tout, il est là pour vous aider mais en aucune manière il est possible d'accéder au BCS sans connaitre le schéma BDCM. Par exemple l'éditeur de Visual Studio n'offre pas d'assistant directement vers SQL Server, ou une autre base de données ou même WCF. Tout doit être fait à la main.

 

L'application

L'application est simple, votre entreprise a fait le choix d'un ECM qui s'appelle RISE (ndlr : ce CMS est disponible dans la galerie Visual Studio).

Dans ce CMS pour l'administration de votre société certains documents ont été publiés. La demande est de créer un connecteur entre ce CMS et SharePoint. Vous avez donc la responsabilité de développer le connecteur.

Il peut être relativement aisé de développer une web part vers le CMS. Mais, on le verra à travers les différents articles, le fait de le faire par un BCS offrira beaucoup d'avantage non négligeable. On abordera aussi les limites de l'éditeur.

Création du projet

Dans Visual Studio on prendra le type de projet Business Data Connectivity Model :

Une fois le projet créé l'éditeur s'ouvre sur le model BDCM.

C'est ici qu'on va travailler le plus pour la configuration, pour le code on a deux class qui sont créés, Entity1 qui représente les données renvoyées, c'est entity1 qui représente le schéma du type de contenu, l'ensemble des champs de votre external content type correspondra à l'ensemble des propriétés de votre entité qui seront mappé dans le schéma BDCM. Ensuite on a Entity1Service qui représentes le chargement des données tous simplement.

On va commencer par donner des noms plus user friendly.

On va mettre RiseDocument à la place de « Entity1 » car on va remplir les entités en partant des tables Document et Content du CMS Rise.

La classe ainsi obtenue RiseDocument contiendra une propriété par champs pertinent de la table:

Voici le schéma des deux tables :

Voici le code de la classe RiseDocument

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 string site { get; set; }

public byte[] Content { get; set; }

}

}

 

Voici le code de la classe RiseDocumentService

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, 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();

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);

rd.site = drData.GetString(6);

}

else

{

rd.DocID = -1;

rd.MimeType = "";

rd.Content = null;

rd.Title = "";

rd.Description = "";

rd.Langue = "";

rd.site = "";

 

}

 

 

}

}

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, 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";

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);

rd.site = drData.GetString(6);

rds.Add(rd);

}

 

}

}

return rds;

}

 

}

}

 

On va changer aussi le nom ET le type de l'identifier de notre entity RiseDocument :

Le BDC Explorer

Lorsque le model BCS est ouvert (et uniquement dans ce cas) une fenêtre apparait, le BDC Explorer :

Il peut être très pratique de mettre la fenêtre des propriétés en dessous du BDC Explorer, il sera ainsi plus facile de travailler avec les type descriptor, On renomme le model pour avoir des noms plus simple :

Pour cela on va utiliser la fenêtre des propriétés pour renommer les model.

Pour la methode ReadItem() :

On renomme l'identifier1 en DocID et les entités en dessous de returnparameter pour coller EXACTEMENT a ce que contient la classe RiseDocument, On ajoute des propriétés (ou type descriptor dans le cas du BDCExplorer) en faisant un clique avec le bouton droit et Add Type Descriptor :

Voici a quoi correspond notre entité :

Il faut bien paramétrer les TypeDescriptor (Nom et Type).

Une fois la partie ReadItem faites on va copier/coller l'entité DocRise en dessous de DocRiseList :

Voici le résultat final :

Quand on a terminé on lance le débuggueur, si vous avez mis des points d'arrêt dans le code ils apparaitront sur la page de profil.

Voici ce qu'on a dans la service application Business Data Service :

On retrouve RiseDocument, on va créer la page de profile en cochant la case à côté de RiseDocument et en cliquen sur Create/Upgrade :

On clique sur OK

Ensuite on va sur la page de profil en remplaçant {0} dans l'url par l'ID de la DB qu'on souhaite voir, ici 2 :

janvier 01
[SharePoint 2010] Bonne année et MVP une année de plus

Bonjour à tous je vous souhaite une très bonne année 2012.

Mon année démarre rapidement puisque je viens d'être renouvelé MVP pour un an de plusJ.

Le programme pour 2012 n'est pas encore définit clairement comme l'année dernière mais beaucoup de choses sont prévu, un ensemble d'article sur les BCS et deux release majeur pour le Pivot Viewer for SharePoint et le Thumbnail extender for SharePoint mais aussi deux autres projets en cours, Pivot Viewer for Office 365 et un quatrième en cours d'analyse.

Xavier VANNESTE

1 - 5Suivante
 

 À 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.
 

 @xvanneste twitter

 
Extraction de données