SharePoint 4 Developers

Guia de referência adicional em desenvolvimento .NET / SharePoint

Business Connectivity Services – Parte V

Explore a interface IContextProperty para obter os detalhes de conexão do BDC. Aprenda como a criar ECTs via Assembly .NET no SharePoint 2010 através do Business Connectivity Services.

Oi pessoal,

Este é mais um artigo da série sobre o BCS. Aprenda a criar ECTs via Assembly .NET no SharePoint 2010 através do Business Connectivity Services!

Esta abordagem irá tirar proveito da interface IContextProperty para obter os detalhes do BDC Connection definido no BDC Model.

Divirtam-se com a leitura!

Criação de ECTs via Assembly .NET

A criação de ECTs via Assembly .NET necessita apenas o VS2010. O SPD2010 não será usado.

Esta abordagem pode ser aplicada em cenários que:

  • Precisem da criação de regras de negócios, que podem ser desenvolvidas no BDC model;
  • Utilizem databases diferentes do SQL Server, que podem ser implementadas na camada de acesso a dados;
  • Exijam o deploy de pacotes WSP para a ativação de features, que é automaticamente gerado pelo VS2010;

Se você possui alguns destes cenários, esta implementação tem um maior nível de dificuldade pelo nível de detalhes na criação do assembly .NET, que é exibido nas próximas seções do artigo.

Trabalhando com o Visual Studio 2010

O template Business Data Connectivity Model será usado neste artigo. Inicie pela abertura do VS2010 e crie um novo projeto de acordo com a Figura 1:

Solution

Figura 1 – Criação de um novo projeto e solução

Na seqüência um Wizard aparece para ajudar no setup do projeto. A URL precisa ser validada para debugging, e a solução será criada como uma Farm Solution, de acordo com a Figura 2:

1part1

Figura 2 – Wizard

OBS: Uma vez que o projeto for criado, apague as classes Entity1 e Entity1Service. Não se esqueça de apagar a entidaded criada que está disponível no BDC Designer, pois novas classes serão geradas em um novo modelo.

Camada de Acesso a Dados

Pelo fato da feature gerar um pacote WSP, decidi por disponibilizar o modelo de acesso a dados no mesmo projeto. Para a manipulação do database é necessária a adição de alguns objetos, e para propósitos de demonstração usarei o LINQ to SQL pois ser mais simples de implementar.

Adicione o LINQ to SQL ao projeto e nomeie de Dev.dbml, então adicione uma nova conexão pelo Server Explorer que utilize Windows Authentication, abra o database e arraste a tabela Contact (Parte II)de acordo com a Figura 3:

LINQtoSQL

Figura 3 – Adição da tabela Contact

Antes de manipularmos os dados da tabela Contact, uma classe que contenha métodos CRUD precisam ser criados. Crie a classe ContactManager e adicione o código abaixo, que está bem documentado:

Code Snippet
  1. public class ContactManager
  2. {
  3.     /// <summary>
  4.     /// Gets all the Contacts
  5.     /// </summary>
  6.     /// <returns>Contacts Array</returns>
  7.     public Contact[] GetContacts()
  8.     {
  9.         var contacts = new List<Contact>();
  10.  
  11.         using (DevDataContext dev = new DevDataContext())
  12.         {
  13.             contacts = (from cont in dev.Contacts
  14.                         select cont).ToList();
  15.         }
  16.         return contacts.ToArray();
  17.     }
  18.  
  19.     /// <summary>
  20.     /// Gets a specific Contact
  21.     /// </summary>
  22.     /// <param name="contactId">Contact Id</param>
  23.     /// <returns>Returns the Contact</returns>
  24.     public Contact GetContactById(int contactId)
  25.     {
  26.         var contact = new Contact();
  27.  
  28.         using (DevDataContext dev = new DevDataContext())
  29.         {
  30.             contact = (from cont in dev.Contacts
  31.                         where cont.ContactID == contactId
  32.                         select cont).First();
  33.         }
  34.         return contact;
  35.     }
  36.  
  37.     /// <summary>
  38.     /// Updates a specific Contact
  39.     /// </summary>
  40.     /// <param name="contact">Contact to be updated</param>
  41.     public void UpdateContact(Contact contact)
  42.     {
  43.         var contactDB = new Contact();
  44.  
  45.         using (DevDataContext dev = new DevDataContext())
  46.         {
  47.             contactDB = (from cont in dev.Contacts
  48.                             where cont.ContactID == contact.ContactID
  49.                             select cont).First();
  50.  
  51.             // Alters the object
  52.             contactDB.Address = contact.Address;
  53.             contactDB.City = contact.City;
  54.             contactDB.CompanyName = contact.CompanyName;
  55.             contactDB.ContactName = contact.ContactName;
  56.             contactDB.ContactTitle = contact.ContactTitle;
  57.             contactDB.Country = contact.Country;
  58.             contactDB.Email = contact.Email;
  59.             contactDB.Fax = contact.Fax;
  60.             contactDB.Phone = contact.Phone;
  61.             contactDB.PostalCode = contact.PostalCode;
  62.             contactDB.Region = contact.Region;
  63.  
  64.             // Submitting the changes
  65.             dev.Refresh(System.Data.Linq.RefreshMode.KeepChanges, contactDB);
  66.             dev.SubmitChanges();
  67.         }
  68.     }
  69.  
  70.     /// <summary>
  71.     /// Adds a Contact
  72.     /// </summary>
  73.     /// <param name="contact">New Contact</param>
  74.     public void AddContact(Contact contact)
  75.     {
  76.         using (DevDataContext dev = new DevDataContext())
  77.         {
  78.             dev.Contacts.InsertOnSubmit(contact);
  79.             dev.SubmitChanges();
  80.         }
  81.     }
  82.  
  83.     /// <summary>
  84.     /// Deletes a Contacts
  85.     /// </summary>
  86.     /// <param name="contactId">Contact Id</param>
  87.     public void DeleteContact(int contactId)
  88.     {
  89.         using (DevDataContext dev = new DevDataContext())
  90.         {
  91.             var contact = (from cont in dev.Contacts
  92.                             where cont.ContactID == contactId
  93.                             select cont).First();
  94.             dev.Contacts.DeleteOnSubmit(contact);
  95.             dev.SubmitChanges();
  96.         }
  97.     }
  98. }

OBS: Este mesmo código já foi explicado na criação de ECTs via Web Services na parte II, porém por ser importante nessa demo, o mesmo código foi reutilizado.

Crie uma partial class chamada DevDataContext, pelo fato de já termos essa classe gerada automaticamente pelo Visual Studio. Crie um novo construtor, de acordo com o código abaixo:

Code Snippet
  1. public partial class DevDataContext
  2.     {
  3.         public DevDataContext() :
  4.             base(BdcModel1.ContactService.GetConnection(), mappingSource)
  5.         {
  6.             OnCreated();
  7.         }
  8.     }

OBS: O novo construtor contém uma chamada ao método GetConnection(), que pertence à classe ContactService e retorna uma connection string, obtida diretamente pelo BDC Metadata Model (veremos adiante).

BDC Model

O Modelo de Metadados será criado utilizando os novos painéis do BDC no Visual Studio. Será criado com base na Camada de Acesso a Dados, pelo fato de utilizarmos a entidade Contact.

Utilize o painel do BDC Designer, de acordo com a Figura 4:

1and2Figura 4 – Adição da entidade Contact

Após a criação da entidade Contact, adicione um Identificador e nomeie de ContactID, também adicione os seguintes Métodos: GetConnection, ReadItem, ReadList, Delete, Update e Create. O menu de contexto nos ajuda nesse caso, conforme a Figura 5:

2

Figura 5 – Adição de Identificador e Métodos

Para adicionar e configurar métodos, a maneira mais conveniente é a utilização do painel BDC Method Details (pelo fato de gerar XML automaticamente) conforme Figura 6:

3

Figura 6 – Painel BDC Method Details

 

A Tabela 1 abaixo mostra um resumo das configurações iniciadas na Figura 6. Contendo todos os métodos e assinaturas:

Option Method Parameters Direction Type Descriptor
Create Creator Method Create returnContact Return ReturnContact
    newContact In NewContact
Create Deleter Method Delete contactID In ContactID
Create Finder Method ReadList contactList Return ContactList
Create Specific Finder Method ReadItem contact Return Contact
    contactID In ContactID
Create Updater Method Update contact In Contact
Create Blank Method GetConnection parameter Return connection
Tabela 1 – Geração automática dos métodos da entidade Contact

OBS: Por padrão um Blank Method criará um método chamado Method. Renomeie para GetConnection.

Antes de configurar os demais métodos, assegure-se de que o tipo do identificador de ContactID é System.Int32. Inicie pelo método ReadItem para configuração e clique sobre o parâmetro (conhecido como type descriptor) Contact, para a seleção de seu tipo conforme a Figura 7:

bdcmethoddetails

Figura 7 – Tipo do TypeDescriptor

O próximo passo é a adição de novos Type Descriptors ao Type Descriptor Contact através do painel BDC Explorer, que basicamente representa seus atributos. A Figura 10 mostra como adicionar Type Descriptors e a Tabela 2 seus detalhes:

6part1Figura 8 – Adição de Type Descriptors

 

Type Descriptor Tipo
Address System.String
City System.String
CompanyName System.String
ContactID System.Int32
ContactName System.String
ContactTitle System.String
Country System.String
Email System.String
Fax System.String
Phone System.String
PostalCode System.String
Region System.String
Tabela 2 – Tipos de Type Descriptors

Quando criados, os Type Descriptors serão reutilizados automaticamente ao criar outros métodos. O código abaixo exibe o XML gerado automaticamente da entidade Contact (após a configuração de todos os métodos). Extraído do arquivo BdcModel1.bdcm:

Code Snippet
  1. <Entity Name="Contact" Namespace="ContactServices.BdcModel.BdcModel1" Version="1.0.0.64">
  2.   <Properties>
  3.     <Property Name="Class" Type="System.String">ContactServices.BdcModel.BdcModel1.ContactService, BdcModel1</Property>
  4.   </Properties>
  5.   <Identifiers>
  6.     <Identifier Name="ContactID" TypeName="System.Int32" />
  7.   </Identifiers>
  8.   <Methods>
  9.     <Method Name="ReadItem">
  10.       <Parameters>
  11.         <Parameter Name="contact" Direction="Return">
  12.           <TypeDescriptor Name="Contact" TypeName="ContactServices.BdcModel.Contact, BdcModel1" IsCollection="false">
  13.             <TypeDescriptors>
  14.               <TypeDescriptor Name="Address" TypeName="System.String" />
  15.               <TypeDescriptor Name="City" TypeName="System.String" />
  16.               <TypeDescriptor Name="CompanyName" TypeName="System.String" />
  17.               <TypeDescriptor Name="ContactID" TypeName="System.Int32" IsCollection="false" IdentifierEntityName="Contact" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierName="ContactID" />
  18.               <TypeDescriptor Name="ContactName" TypeName="System.String" />
  19.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" />
  20.               <TypeDescriptor Name="Country" TypeName="System.String" />
  21.               <TypeDescriptor Name="Email" TypeName="System.String" />
  22.               <TypeDescriptor Name="Fax" TypeName="System.String" />
  23.               <TypeDescriptor Name="Phone" TypeName="System.String" />
  24.               <TypeDescriptor Name="PostalCode" TypeName="System.String" />
  25.               <TypeDescriptor Name="Region" TypeName="System.String" />
  26.             </TypeDescriptors>
  27.           </TypeDescriptor></Parameter>
  28.         <Parameter Name="contactID" Direction="In">
  29.           <TypeDescriptor Name="ContactID" TypeName="System.Int32" IdentifierEntityName="Contact" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierName="ContactID" /></Parameter>
  30.       </Parameters>
  31.       <MethodInstances>
  32.         <MethodInstance Name="ReadItem" Type="SpecificFinder" ReturnParameterName="contact" ReturnTypeDescriptorPath="Contact" />
  33.       </MethodInstances></Method>
  34.     <Method Name="ReadList">
  35.       <Parameters>
  36.         <Parameter Name="contactList" Direction="Return">
  37.           <TypeDescriptor Name="ContactList" TypeName="System.Collections.Generic.IEnumerable`1[[ContactServices.BdcModel.Contact, BdcModel1]]" IsCollection="true">
  38.             <TypeDescriptors>
  39.               <TypeDescriptor Name="Contact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  40.                 <TypeDescriptors>
  41.                   <TypeDescriptor Name="Address" TypeName="System.String" />
  42.                   <TypeDescriptor Name="City" TypeName="System.String" />
  43.                   <TypeDescriptor Name="CompanyName" TypeName="System.String" />
  44.                   <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" />
  45.                   <TypeDescriptor Name="ContactName" TypeName="System.String" />
  46.                   <TypeDescriptor Name="ContactTitle" TypeName="System.String" />
  47.                   <TypeDescriptor Name="Country" TypeName="System.String" />
  48.                   <TypeDescriptor Name="Email" TypeName="System.String" />
  49.                   <TypeDescriptor Name="Fax" TypeName="System.String" />
  50.                   <TypeDescriptor Name="Phone" TypeName="System.String" />
  51.                   <TypeDescriptor Name="PostalCode" TypeName="System.String" />
  52.                   <TypeDescriptor Name="Region" TypeName="System.String" /></TypeDescriptors></TypeDescriptor></TypeDescriptors></TypeDescriptor></Parameter>
  53.       </Parameters>
  54.       <MethodInstances>
  55.         <MethodInstance Name="ReadList" Type="Finder" ReturnParameterName="contactList" ReturnTypeDescriptorPath="ContactList" />
  56.       </MethodInstances></Method>
  57.     <Method Name="Create">
  58.       <Parameters>
  59.         <Parameter Name="returnContact" Direction="Return">
  60.           <TypeDescriptor Name="ReturnContact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  61.             <TypeDescriptors>
  62.               <TypeDescriptor Name="Address" TypeName="System.String" />
  63.               <TypeDescriptor Name="City" TypeName="System.String" />
  64.               <TypeDescriptor Name="CompanyName" TypeName="System.String" />
  65.               <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" />
  66.               <TypeDescriptor Name="ContactName" TypeName="System.String" />
  67.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" />
  68.               <TypeDescriptor Name="Country" TypeName="System.String" />
  69.               <TypeDescriptor Name="Email" TypeName="System.String" />
  70.               <TypeDescriptor Name="Fax" TypeName="System.String" />
  71.               <TypeDescriptor Name="Phone" TypeName="System.String" />
  72.               <TypeDescriptor Name="PostalCode" TypeName="System.String" />
  73.               <TypeDescriptor Name="Region" TypeName="System.String" /></TypeDescriptors></TypeDescriptor></Parameter>
  74.         <Parameter Name="newContact" Direction="In">
  75.           <TypeDescriptor Name="NewContact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  76.             <TypeDescriptors>
  77.               <TypeDescriptor Name="Address" TypeName="System.String" CreatorField="true" />
  78.               <TypeDescriptor Name="City" TypeName="System.String" CreatorField="true" />
  79.               <TypeDescriptor Name="CompanyName" TypeName="System.String" CreatorField="true" />
  80.               <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" CreatorField="true" />
  81.               <TypeDescriptor Name="ContactName" TypeName="System.String" CreatorField="true" />
  82.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" CreatorField="true" />
  83.               <TypeDescriptor Name="Country" TypeName="System.String" CreatorField="true" />
  84.               <TypeDescriptor Name="Email" TypeName="System.String" CreatorField="true" />
  85.               <TypeDescriptor Name="Fax" TypeName="System.String" CreatorField="true" />
  86.               <TypeDescriptor Name="Phone" TypeName="System.String" CreatorField="true" />
  87.               <TypeDescriptor Name="PostalCode" TypeName="System.String" CreatorField="true" />
  88.               <TypeDescriptor Name="Region" TypeName="System.String" CreatorField="true" /></TypeDescriptors></TypeDescriptor></Parameter>
  89.       </Parameters>
  90.       <MethodInstances>
  91.         <MethodInstance Name="Create" Type="Creator" ReturnParameterName="returnContact" ReturnTypeDescriptorPath="ReturnContact" />
  92.       </MethodInstances></Method>
  93.     <Method Name="Update">
  94.       <Parameters>
  95.         <Parameter Name="contact" Direction="In">
  96.           <TypeDescriptor Name="Contact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  97.             <TypeDescriptors>
  98.               <TypeDescriptor Name="Address" TypeName="System.String" UpdaterField="true" />
  99.               <TypeDescriptor Name="City" TypeName="System.String" UpdaterField="true" />
  100.               <TypeDescriptor Name="CompanyName" TypeName="System.String" UpdaterField="true" />
  101.               <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" UpdaterField="true" />
  102.               <TypeDescriptor Name="ContactName" TypeName="System.String" UpdaterField="true" />
  103.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" UpdaterField="true" />
  104.               <TypeDescriptor Name="Country" TypeName="System.String" UpdaterField="true" />
  105.               <TypeDescriptor Name="Email" TypeName="System.String" UpdaterField="true" />
  106.               <TypeDescriptor Name="Fax" TypeName="System.String" UpdaterField="true" />
  107.               <TypeDescriptor Name="Phone" TypeName="System.String" UpdaterField="true" />
  108.               <TypeDescriptor Name="PostalCode" TypeName="System.String" UpdaterField="true" />
  109.               <TypeDescriptor Name="Region" TypeName="System.String" UpdaterField="true" /></TypeDescriptors></TypeDescriptor></Parameter>
  110.       </Parameters>
  111.       <MethodInstances>
  112.         <MethodInstance Name="Update" Type="Updater" />
  113.       </MethodInstances></Method>
  114.     <Method Name="Delete">
  115.       <Parameters>
  116.         <Parameter Name="contactID" Direction="In">
  117.           <TypeDescriptor Name="ContactID" TypeName="System.Int32" IdentifierEntityName="Contact" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierName="ContactID" /></Parameter>
  118.       </Parameters>
  119.       <MethodInstances>
  120.         <MethodInstance Name="Delete" Type="Deleter" />
  121.       </MethodInstances></Method>
  122.     <Method Name="GetConnection">
  123.       <Parameters>
  124.         <Parameter Name="parameter" Direction="Return">
  125.           <TypeDescriptor Name="connection" TypeName="System.String" /></Parameter>
  126.       </Parameters></Method>
  127.   </Methods>
  128.   </Entity>

OBS: O arquivo BdcModel1.bdcm pode ser visualizado em XML diretamente no Visual Studio, utilize o menu de contexto Open With... e então XML (Text) Editor.

BDC Model Connection

Os detalhes de conexão podem ser definidos dentro das propriedades do LobSystemInstance se você utilizar um database ou web service. Como isso se aplica no cenário dessa demo, temos o código abaixo:

Code Snippet
  1. <LobSystemInstance Name="BdcModel1">
  2.   <Properties>
  3.     <Property Name="AuthenticationMode" Type="System.String">PassThrough</Property>
  4.     <!-- AuthenticationMode can be set to PassThrough, RevertToSelf, RdbCredentials, or WindowsCredentials. -->
  5.     <Property Name="DatabaseAccessProvider" Type="System.String">SqlServer</Property>
  6.     <!-- Options:  SQL Server, OleDB, Oracle, or ODBC. -->
  7.     <Property Name="RdbConnection Data Source" Type="System.String">W2008R2Sub1</Property>
  8.     <!-- Type the database server name or the SQL Server instance name in the format SQLServer\Instance. -->
  9.     <Property Name="RdbConnection Initial Catalog" Type="System.String">Dev</Property>
  10.     <!-- Type the database name. -->
  11.     <Property Name="RdbConnection Integrated Security" Type="System.String">SSPI</Property>
  12.     <!-- Type SSPI for Integrated Security. -->
  13.     <Property Name="RdbConnection Pooling" Type="System.String">false</Property>
  14.     <!-- Type true or false for Pooling -->
  15.   </Properties>
  16. </LobSystemInstance>

OBS: Se você quiser saber mais sobre os tipos de autenticação disponíveis através do BCS, verifique a seção Referências. Basicamente o XML acima contém propriedades comumente usadas na criação de connection strings.

Métodos da Entidade do BDC Model

Durante a criação dos métodos através dos painéis do BDC, o Visual Studio ao mesmo tempo foi gerando automaticamente a classe ContactService e seus respectivos métodos. Eles ainda não estão implementados, pois estão gerando a exceção do tipo NotImplementedException.

Antes de codificarmos, você se lembra do código que contém o método GetConnection? Ele precisa retornar a connection string de um database, mas como? Exploraremos as propriedades do LobSystemInstance definidas previamente.

Mas como ler o XML que contém essas propriedades? Fácil! Apenas implemente a interface IContextProperty na classe ContactService e o BDC se encarrega do resto.

OBS: Quando um assembly possui uma classe que implementa IContextProperty, suas propriedades são inicializadas automaticamente no momento que o assembly é executado no BDC. Isso é uma mão na roda!

Adicione a referência ao assembly Microsoft.Business, que está disponível no diretório 14: \ISAPI\Microsoft.BusinessData.dll.

Observe o código abaixo, que exibe a classe ContactService:

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using ContactServices.BdcModel;
  6. using Microsoft.BusinessData.SystemSpecific;
  7. using Microsoft.BusinessData.MetadataModel;
  8. using Microsoft.BusinessData.Runtime;
  9. using Microsoft.BusinessData.MetadataModel.Collections;
  10.  
  11. namespace ContactServices.BdcModel.BdcModel1
  12. {
  13.     public partial class ContactService : IContextProperty
  14.     {
  15.         private static IMethodInstance methodInstance;
  16.         private static ILobSystemInstance lobSystemInstance;
  17.         private static IExecutionContext executionContext;
  18.  
  19.         #region IContextProperty implementation
  20.  
  21.         public IMethodInstance MethodInstance
  22.         {
  23.             get { return methodInstance; }
  24.             set { methodInstance = value; }
  25.         }
  26.  
  27.         public ILobSystemInstance LobSystemInstance
  28.         {
  29.             get { return lobSystemInstance; }
  30.             set { lobSystemInstance = value; }
  31.         }
  32.  
  33.         public IExecutionContext ExecutionContext
  34.         {
  35.             get { return executionContext; }
  36.             set { executionContext = value; }
  37.         }
  38.  
  39.         #endregion
  40.  
  41.         public static Contact ReadItem(int contactID)
  42.         {
  43.             // Implement your own business rules
  44.             return new ContactManager().GetContactById(contactID);
  45.         }
  46.  
  47.         public static IEnumerable<Contact> ReadList()
  48.         {
  49.             // Implement your own business rules
  50.             return new ContactManager().GetContacts();
  51.         }
  52.  
  53.         public static Contact Create(Contact newContact)
  54.         {
  55.             if (string.IsNullOrEmpty(newContact.ContactName) || string.IsNullOrEmpty(newContact.Email) || string.IsNullOrEmpty(newContact.Phone))
  56.                 throw new ObjectNotFoundException("ContactName, Email and Phone are mandatories.");
  57.  
  58.             var manager = new ContactManager();
  59.             manager.AddContact(newContact);
  60.             return manager.GetContactById(newContact.ContactID);
  61.         }
  62.  
  63.         public static void Update(Contact contact)
  64.         {
  65.             if (string.IsNullOrEmpty(contact.ContactName) || string.IsNullOrEmpty(contact.Email) || string.IsNullOrEmpty(contact.Phone))
  66.                 throw new ObjectNotFoundException("ContactName, Email and Phone are mandatories.");
  67.  
  68.             new ContactManager().UpdateContact(contact);
  69.         }
  70.  
  71.         public static void Delete(int contactID)
  72.         {
  73.             // Implement your own business rules
  74.             new ContactManager().DeleteContact(contactID);
  75.         }
  76.  
  77.         public static string GetConnection()
  78.         {
  79.             INamedPropertyDictionary properties = lobSystemInstance.GetProperties();
  80.  
  81.             string template = "Data Source={0};Initial Catalog={1};Integrated Security={2};";
  82.  
  83.             string dataSource = "RdbConnection Data Source";
  84.             string initialCatalog = "RdbConnection Initial Catalog";
  85.             string integratedSecurity = "RdbConnection Integrated Security";
  86.  
  87.             if (!properties.ContainsKey(dataSource) || !properties.ContainsKey(initialCatalog) || !properties.ContainsKey(integratedSecurity))
  88.                 throw new Exception("LobSystemInstance does not contain a connection string");
  89.  
  90.             return string.Format(template, properties[dataSource].ToString(), properties[initialCatalog].ToString(), properties[integratedSecurity].ToString());
  91.  
  92.         }
  93.     }
  94. }

Em exceçào ao método GetConnection, todos os outros chamam métodos CRUD da classe ContactManager. Ainda, nos métodos Create e Update existe uma validação de campos obrigatórios ContactName, Email e Phone, que não podem ser nulos ou vazios pois geram uma exceção do tipo ObjectNotFoundException.

Como esperado, o método GetConnection obtém as propriedades de LobSystemInstance, que contém os detalhes de conexão do BDC, e retorna a connection string utilizada no construtor da Partial Class DevDataContext.

Criando o Pacote de Deploy

O deploy de pacotes WSP no mundo real é feito ou manualmente ou utilizando scripts, e não diretamente com a intervenção do Visual Studio. Estou apenas explicando isso para propósitos de demonstração e entendimento do STSADM.

Antes de gerar o pacotes WSP, mais algumas configurações são necessárias. Renomeie a feature para BdcModelFeature e adicione a propriedade SiteUrl no arquivo XML BdcModelFeature.Template.xml, de acordo com a Figura 9:

9_680 Figura 9 – Propriedades da Feature

Finalmente gere o pacote WSP ao selecionar Package no menu de contexto do Visual Studio. Pegue o pacote no diretório Bin e utilizando o STSADM faça o deploy utilizando os seguintes comandos:

stsadm -o addsolution -filename "ContactServices.BdcModel.wsp"

stsadm -o deploysolution -name "ContactServices.BdcModel.wsp" -allowGacDeployment –immediate

stsadm -o execadmsvcjobs

stsadm -o installfeature -filename "ContactServices.BdcModel_BdcModelFeature\feature.xml" –force

stsadm -o activatefeature -name "ContactServices.BdcModel_BdcModelFeature"

OBS: Faça o download da solução aqui.

Configurando a External List

Nesse estágio já é possível a criação da External List que proverá uma interface visual para os dados externos no SharePoint 2010. Tanto pelo SharePoint Designer quanto pela interface do SharePoint é possível a criação de External Lists, na Parte II mostrei como utilizar o SharePoint Designer para essa tarefa, e agora vou mostrar como utilizar a interface visual do SharePoint para isso.

Vá até o web site e acesse Site Actions > More Options. A Figura 10 exibe um modal dialog para selecionarmos a External List:

10
Figura 10 – Seleção da External List

Então escolha o External Content Type ContactServices.BdcModel.BdcModel1.Contact e crie a Lista Contacts, conforme exibido na Figura 11:

11_680
Figura 11 – Criação da External List Contacts

Depois disso oteremos a Lista Contacts criada. É só isso? Não, precisamos definir as permissões no BDC Service Application para este Assembly, do contrário obteremos a seguinte tela:

BDC1
Figura 12 – Acesso negado pelo Business Data Connectivity

Definindo as Permissões do BDC

Após o deploy do Assembly .NET, precisamos definir permissões apropriadas no BDC Service Application para que os usuários visualizem os dados externos. Vá ao BDC Service Application em Central Administration e encontre o Assembly .NET:

BDC2_680
Figura 13 – Procurando o .NET Assembly

Então defina os usuários que possuirão permissão para visualizar o conteúdo dos dados externos, conforme a Figura 14:

BDC3_680
Figura 14 – Definindo permissões no BDC

Ao fazer isso, dê um refresh na External List (Figura 12) e você obterá os dados externos. Smile

Esse artigo foi de um nível mais avançado pessoal, daqui para frente vocês estarão aptos a criarem seus próprios ECTs via Assemblies .NET.

A série sobre o BDC ainda nào está finalizada, da próxima vez falarei sobre como interfacear ECTs com Client Applications. Até a próxima!

Referências:
http://msdn.microsoft.com/en-us/library/ee556826(v=office.14).aspx
http://msdn.microsoft.com/en-us/library/microsoft.businessdata.systemspecific.icontextproperty(office.14).aspx

[]'s

Marcel Medina

Clique aqui para ler o mesmo conteúdo em Inglês.

Business Connectivity Services – Parte IV

Entenda a estrutura hier&#225;rquica do modelo de metadados do BDC (Business Data Connectivity Model) e as novas ferramentas do Visual Studio 2010 para design de modelos do BDC (Parte IV)

Oi pessoal, tudo bem?

Essa é a quarta parte do artigo sobre as novidades de integração de dados externos com o Business Connectivity Services (BCS) no SharePoint 2010!

Apenas para recapitular, na parte I do artigo tivemos uma introdução ao funcionamento do BCS pela análise de sua arquitetura e componentes, na parte II tivemos a oportunidade de criar External Content Types (ECT) via Database e na parte III trabalhamos na criação de ECTs via Web Service.

A leitura da parte I é extremamente importante para o entendimento desta parte. Nesse artigo vou explicar a estrutura hierárquica do modelo de metadados do BDC (Business Data Connectivity Model) e dar uma introdução às novas ferramentas do Visual Studio 2010 na criação de objetos do BDC.

Boa leitura!

Entendendo o Modelo de Metadados do BDC

No exemplo desse artigo trabalharemos com um novo template do Visual Studio 2010 chamado Business Data Connectivity (BDC) Model, que permite a criação de Entidades (BDC Entities) também conhecidas como External Content Types, que já vimos na parte I.

As entidades são objetos que compõem o modelo de metadados do BDC, que representam o núcleo de funcionamento do BDC. Nessa abordagem quero ir um pouco mais a fundo nesse modelo, vejamos a Figura 1:

BDCModelFigura 1 - Modelo de Metadados do BDC

Agora fica claro onde os ECTs estão dentro do Modelo de Metadados do BDC, mas ainda não conhecemos em detalhes o papel de cada um desses objetos que compõem a Figura 1, apenas podemos notar que os objetos estão em uma estrutura hierárquica.

Para entendimento desses objetos veremos o detalhamento de cada um:

OBS: Esse conteúdo pode ser encontrado na seção referências, porém resolvi detalhar mais do que o conteúdo encontrado no MSDN. :)

  • Model - Esse é objeto principal, núcleo do funcionamento do BDC que mapeia os dados externos. Trata-se do agrupador de todos os objetos que compõem a hierarquia desse modelo.

  • LobSystem - Dentro do modelo figura como sendo a representação de um serviço externo que contém a lógica de negócio, simplesmente pelo fato de definir o tipo da fonte de dados externos que será utilizada, podendo ser:
  1. Database – Define o mapeamento de um banco de dados;
  2. DotNetAssembly – Define o mapeamento de um assembly .NET;
  3. Wcf – Define o mapeamento de um endpoint do serviço WCF;
  4. WebService – Define o mapeamento de um Web Service. Considerado “deprecated”, portanto utilize um serviço WCF;
  5. Custom – Define o mapeamento de um Conector customizado, implementado para gerenciar a conexão e a transferência de dados.
  • LobSystemInstance - Trata-se da implementação de um LobSystem. Contém todos os detalhes de conexão a um serviço externo para a criação da instância de um LobSystem.

  • Entity - Trata-se da representação dentro do modelo de metadados do BDC de um ECT do BCS, que conforme já visto na Parte I determina o schema de dados da entidade, utiliza-se de recursos de acesso a dados e disponibiliza um comportamento dentro do Office e SharePoint através de métodos.

  • Identifier - Um identificador funciona como uma chave primária nas entidades.

  • Method - Os métodos são os comportamentos de uma entidade. Dentro do modelo funciona como um agrupador das configurações (FilterDescriptor, Parameter, MethodInstance) do método que representa.

  • FilterDescriptor - Basicamente um filterdescriptor pode ser criado dentro de um método para selecionar tanto a entrada quanto o retorno de valores do mesmo. Diversos tipos de filtros podem ser utilizados (veja a seção referências).

  • Parameter - Define o tipo de parâmetro que será utilizado dentro do método, sendo:
  1. In – Utilizado para parâmetros de entrada;
  2. Out – Utilizado para parâmetros de saída, similar ao parâmetro "out" em C#.
  3. InOut – Representa um parâmetro que tem as duas funções (entrada / saída), similar ao parâmetro "ref" em C#.
  4. Return – Define o tipo para retorno de um método, no BDC isso é considerado como um parâmetro de retorno.
  • TypeDescriptor - Um typedescriptor é nada mais nada menos do que uma definição do tipo do parâmetro. Ex: Int32, String. É recursivo, pois permite que outro typedescriptor seja referenciado como sendo o tipo de um parâmetro.

  • MethodInstance - Trata-se da implementação de um Method. As operações Create, Update, ReadItem, ReadList e Delete já são pré-definidas para utilização.

  • Action - As ações possibilitam a adição de funcionalidades extras aos ECTs, pois funcionam como um link adicional aos dados externos. Por padrão as ações View Item, Edit Item, e Delete Item são adicionadas na interface do usuário (veja a seção referências) e qualquer nova ação adicionada, como por exemplo um link para abrir uma página, acompanha o ECT em qualquer parte do SharePoint.

  • ActionParameter - Define a URL da ação que se refere para o funcionamento do link criado. Utiliza-se de identificadores ou typedescriptors da entidade para a criação da URL.

  • AssociationGroup - Associações representam os relacionamentos entre as entidades, similar a um relacionamento de tabelas. Um AssociationGroup deve ser utilizado para amarrar métodos de associação que são aplicados em um relacionamento de entidades. Ex: Considerando duas entidades Cliente e Pedido, um AssociationGroup armazenaria métodos como ObterPedidosPorCliente e ObterClientePorPedido.

OBS: Na próxima parte dessa lição trabalharemos com a maioria desses objetos, e esse overview vai ser consolidado ao colocarmos a mão na massa, principalmente quando trabalharmos com o XML que está por trás dessas definições.

Ferramenta de Design para o Modelo de Metadados do BDC

O Visual Studio 2010 foi turbinado com várias novas ferramentas para design e o BDC não ficou de fora. Agora ficou mais fácil a criação de modelos no BDC, pois o mais trabalhoso (a criação da maioria dos objetos) pode ser feito visualmente e outros pequenos detalhes podem ser feitos manualmente no XML gerado.

A Figura 2 mostra os novos painéis que estão disponíveis no VS2010 para design de modelos no BDC:

NewDesignerFigura 2 - Painéis para design de modelos do BDC

Com exceção do painel de Propriedades, três (3) novos painéis foram incorporados ao VS2010. São eles:

  • BDC Designer - Possibilita a criação e edição de Entidades, Identificadores, Métodos e Associações entre as Entidades. Trata-se de uma área para design que permite a criação dos objetos via drag-and-drop da palheta Toolbox ou mesmo utilizando o menu de contexto (pelo botão direito do mouse).

  • BDC Method Details - Assim como o próprio nome diz, exibe os detalhes de configuração dos métodos. Permite a criação e edição de métodos, parâmetros, typedescriptors e filtros (conforme o modelo de metadados do BDC).

  • BDC Explorer - Organiza e exibe os objetos do modelo de metadados do BDC em uma tree view. Sua principal finalidade é o de apresentar os objetos numa estrutura hierárquica, porém também permite a criação de typedescriptors e validação dos objetos.

Durante o desenvolvimento na próxima parte veremos como manipular os objetos do Modelo de Metadados do BDC por esses painéis. Aguardem!

Referências:
http://msdn.microsoft.com/en-US/library/ee556378.aspx
http://msdn.microsoft.com/en-us/library/ee557835.aspx
http://msdn.microsoft.com/en-us/library/ee559393.aspx

[]’s

Marcel Medina

Clique aqui para ler o mesmo conteúdo em Inglês.

Business Connectivity Services – Parte III

Nessa abordagem aprenda a integrar servi&#231;os WCF no SharePoint 2010 pelo Business Connectivity Services. Essa &#233; uma abordagem bem interessante, pois permite que diferentes servi&#231;os (inclusive da nuvem) possam ser integrados no SharePoint 2010.

Oi pessoal, tudo bem?

Depois de umas mini-férias trago mais uma parte da série sobre o BCS, onde abordo como conectar a diferentes fontes de dados externos.

Nessa abordagem aprenda a integrar serviços WCF no SharePoint 2010 pelo Business Connectivity Services. Essa é uma abordagem bem interessante, pois permite que diferentes serviços (inclusive da nuvem) possam ser integrados no SharePoint 2010.

Para a apresentação desse artigo criaremos um serviço WCF, que servirá para a criação de um External Content Type (ECT).

Criação de ECTs via Web Service (WCF)

Para a criação de ECTs via Web Service necessitamos da utilização do SPD2010 e nesse caso, como iremos criar um Web Service, necessitamos do VS2010.

Esse tipo de abordagem é aplicado em ambientes que:

  • Façam integração com uma fonte de dados externos (ex: outros sistemas), quer seja em sua Intranet ou Internet;
  • Haja a necessidade de criação de regras de negócio, o que pode ser implementado durante a criação do Web Service;
  • Utilizem bancos de dados diferentes do SQL Server, o que pode ser implementado na camada de acesso a dados durante a criação do Web Service;

Caso você tenha esse cenário, essa implementação tem um nível maior de dificuldade pela criação do Web Service, que é demonstrado a seguir. Inicialmente trabalharemos com o VS2010 e em seguida finalizaremos a configuração com o SPD2010.

Trabalhando com o Visual Studio 2010

A criação do ECT em questão só é possível com a existência de um Web Service, para tal criaremos uma solução no VS2010. Conforme já mencionado no Bloco 1 da Arquitetura do BCS (Parte I), ambas as extensões .asmx (ASP.NET Web Service Application) e .svc (WCF Service Application) podem ser utilizadas na criação de ECTs e nessa demonstração vou utilizar um WCF Service Application.

Inicie o VS2010, crie uma Blank Solution e adicione 3 projetos conforme a Figura 1:

solution

Figura 1 - Criação da Solução

OBS: Com relação aos arquivos *.cs e App.config disponibilizados por padrão quando da criação de novos projetos, favor excluí-los.

A solução foi separada em projetos que refletem as camadas de acesso a dados e negócio que veremos a seguir. É necessário antes que as seguintes referências sejam adicionadas entre os projetos conforme a Tabela 1:

Projeto Referência
ContactServices.Business ContactServices.Data
ContactServices.Host ContactServices.Business
Tabela 1 - Referências

OBS: Em todos os exemplos de código, meu objetivo é de mostrar apenas a funcionalidade na criação de um ECT no SharePoint 2010, portanto utilize o código como base e implemente os tratamentos que toda aplicação necessita possuir (ex: Logs, Exceções, Segurança, etc...). Recomendo a utilização do Enterprise Library.

Camada de Acesso a Dados

Para a criação do projeto ContactServices.Data precisamos adicionar alguns objetos que manipulem o banco de dados, e para fins de demonstração utilizo o LINQ to SQL por ser mais simples de implementar. Adicione esse objeto ao projeto e o nomeie de Dev.dbml, em seguida crie pelo Server Explorer uma nova conexão que utilize Windows Authentication, abra o database e arraste a tabela Contact (Parte II) conforme demonstrado na Figura 2:

LINQtoSQL

Figura 2 - Adição da tabela Contact

Para manipularmos os dados do objeto Contact é necessário criarmos uma classe que disponibilize métodos de um CRUD, para isso crie uma classe chamada ContactManager e adicione o código abaixo, cujos comentários são bem explicativos:

Code Snippet
  1. public class ContactManager
  2. {
  3.     /// <summary>
  4.     /// Obtem todos os Contatos
  5.     /// </summary>
  6.     /// <returns>Array de Contatos</returns>
  7.     public Contact[] GetContacts()
  8.     {
  9.         var contacts = new List<Contact>();
  10.  
  11.         using (DevDataContext dev = new DevDataContext())
  12.         {
  13.             contacts = (from cont in dev.Contacts
  14.                         select cont).ToList();
  15.         }
  16.         return contacts.ToArray();
  17.     }
  18.  
  19.     /// <summary>
  20.     /// Obtem um Contato especifico
  21.     /// </summary>
  22.     /// <param name="contactId">Id do Contato</param>
  23.     /// <returns>Retorna o Contato</returns>
  24.     public Contact GetContactById(int contactId)
  25.     {
  26.         var contact = new Contact();
  27.  
  28.         using (DevDataContext dev = new DevDataContext())
  29.         {
  30.             contact = (from cont in dev.Contacts
  31.                         where cont.ContactID == contactId
  32.                         select cont).First();
  33.         }
  34.         return contact;
  35.     }
  36.  
  37.     /// <summary>
  38.     /// Atualiza um Contato especifico
  39.     /// </summary>
  40.     /// <param name="contact">Contato para atualizacao</param>
  41.     public void UpdateContact(Contact contact)
  42.     {
  43.         var contactDB = new Contact();
  44.  
  45.         using (DevDataContext dev = new DevDataContext())
  46.         {
  47.             contactDB = (from cont in dev.Contacts
  48.                             where cont.ContactID == contact.ContactID
  49.                             select cont).First();
  50.  
  51.             // Alterando o objeto
  52.             contactDB.Address = contact.Address;
  53.             contactDB.City = contact.City;
  54.             contactDB.CompanyName = contact.CompanyName;
  55.             contactDB.ContactName = contact.ContactName;
  56.             contactDB.ContactTitle = contact.ContactTitle;
  57.             contactDB.Country = contact.Country;
  58.             contactDB.Email = contact.Email;
  59.             contactDB.Fax = contact.Fax;
  60.             contactDB.Phone = contact.Phone;
  61.             contactDB.PostalCode = contact.PostalCode;
  62.             contactDB.Region = contact.Region;
  63.  
  64.             dev.Refresh(System.Data.Linq.RefreshMode.KeepChanges, contactDB);
  65.             dev.SubmitChanges();
  66.         }
  67.     }
  68.  
  69.     /// <summary>
  70.     /// Adiciona um Contato
  71.     /// </summary>
  72.     /// <param name="contact">Novo Contato</param>
  73.     public void AddContact(Contact contact)
  74.     {
  75.         using (DevDataContext dev = new DevDataContext())
  76.         {
  77.             dev.Contacts.InsertOnSubmit(contact);
  78.             dev.SubmitChanges();
  79.         }
  80.     }
  81.  
  82.     /// <summary>
  83.     /// Apaga um Contato
  84.     /// </summary>
  85.     /// <param name="contactId">Id do Contato</param>
  86.     public void DeleteContact(int contactId)
  87.     {
  88.         using (DevDataContext dev = new DevDataContext())
  89.         {
  90.             var contact = (from cont in dev.Contacts
  91.                             where cont.ContactID == contactId
  92.                             select cont).First();
  93.             dev.Contacts.DeleteOnSubmit(contact);
  94.             dev.SubmitChanges();
  95.         }
  96.     }
  97. }

Camada de Negócio

No projeto ContactServices.Business devemos disponibilizar Interfaces e Classes que façam chamadas aos métodos do projeto ContactServices.Data. A criação de Interfaces é importante por 3 motivos na solução:

  • Definição de um contrato para os métodos;
  • Determina um comportamento nas classes que a implementam;
  • Utilização pelo WCF Service Application (projeto ContactServices.Host);

Para implementação do projeto, crie a interface IContactServices e a classe que a implementa chamada ContactServices, conforme os códigos abaixo respectivamente:

Code Snippet
  1. [ServiceContract]
  2. public interface IContactServices
  3. {
  4.     [OperationContract]
  5.     Contact[] GetContacts();
  6.  
  7.     [OperationContract]
  8.     Contact GetContactById(int contactId);
  9.  
  10.     [OperationContract]
  11.     void UpdateContact(Contact contact);
  12.  
  13.     [OperationContract]
  14.     void AddContact(Contact contact);
  15.  
  16.     [OperationContract]
  17.     void DeleteContact(int contactId);
  18. }

 

Code Snippet
  1. public class ContactServices : IContactServices
  2. {
  3.     #region IContactServices Members
  4.  
  5.     public Contact[] GetContacts()
  6.     {
  7.         // Implemente sua propria regra de negocio
  8.         return new ContactManager().GetContacts();
  9.     }
  10.  
  11.     public Contact GetContactById(int contactId)
  12.     {
  13.         // Implemente sua propria regra de negocio
  14.         return new ContactManager().GetContactById(contactId);
  15.     }
  16.  
  17.     public void UpdateContact(Contact contact)
  18.     {
  19.         // Implemente sua propria regra de negocio
  20.         new ContactManager().UpdateContact(contact);
  21.     }
  22.  
  23.     public void AddContact(Contact contact)
  24.     {
  25.         // Implemente sua propria regra de negocio
  26.         new ContactManager().AddContact(contact);
  27.     }
  28.  
  29.     public void DeleteContact(int contactId)
  30.     {
  31.         // Implemente sua propria regra de negocio
  32.         new ContactManager().DeleteContact(contactId);
  33.     }
  34.  
  35.     #endregion
  36. }

 

A classe ContactServices disponibiliza métodos de um CRUD que serão utilizados no BCS e falam por si só. Servem como uma “casquinha” para a manipulação de dados, pois chamam diretamente os métodos da classe ContactManager do projeto ContactServices.Data.

Nesse caso não foram implementadas regras de negócio, mas se você tiver necessidade faça a implementação nesses métodos.

Host do Serviço

O projeto ContactServices.Host servirá para fazer o host do serviço WCF, que vai disponibilizar os métodos para o BCS. Para isso renomeie o arquivo criado por padrão Service1.svc para ContactServices.svc e altere a referência do serviço na diretiva de página para:

Code Snippet
  1. <%@ ServiceHost Language="C#" Debug="true" Service="ContactServices.Business.ContactServices" %>

 

Essa alteração é necessária para o mapeamento da classe ContactServices implementada no projeto ContactServices.Business. Para que o serviço seja disponibilizado também é necessária a alteração do Web.config, que pode ser editado pelo WCF Service Configuration Editor (disponível no VS2010) ou diretamente no arquivo na seção system.serviceModel conforme o código abaixo:

Code Snippet
  1. <system.serviceModel>
  2.     <services>
  3.       <service behaviorConfiguration="ContactServicesBehavior" name="ContactServices.Business.ContactServices">
  4.         <endpoint binding="wsHttpBinding" bindingConfiguration="" contract="ContactServices.Business.IContactServices" />
  5.         <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" contract="ContactServices.Business.IContactServices" />
  6.       </service>
  7.     </services>
  8.     <behaviors>
  9.       <serviceBehaviors>
  10.         <behavior name="ContactServicesBehavior">
  11.           <serviceMetadata httpGetEnabled="true" />
  12.           <serviceDebug includeExceptionDetailInFaults="true" />
  13.         </behavior>
  14.       </serviceBehaviors>
  15.     </behaviors>
  16.   </system.serviceModel>

OBS: O behavior serviceDebug contém o atributo includeExceptionDetailInFaults para listar em detalhes qualquer problema do Web Service no Log do SharePoint, o que é bastante útil durante os testes na integração do serviço WCF.

Ao final essa solução deve estar semelhante à exibida na Figura 3:

vstudio

Figura 3 - Solução Final

Faça o deploy da solução no IIS para que utilizemos um endereço fixo na criação do ECT, que veremos a seguir.

Trabalhando com o SharePoint Designer 2010

Nessa etapa já temos a solução criada e precisamos apenas criar o ECT, mapeando os métodos e parâmetros do Web Service. A Figura 1 (Parte II) nos mostra a etapa inicial de criação do ECT, em seguida adicione uma nova conexão (1) ao Web Service pela seleção do tipo do External Data Source (2), conforme Figura 4:

conexao

Figura 4 - Criação de uma nova conexão

Defina os parâmetros de conexão conforme a Figura 5:

WCF

Figura 5 - Detalhes da conexão

OBS: Algumas considerações importantes:

  • Os metadados do WCF podem ser obtidos pelo WSDL ou utilizando o endpoint Mex. Ambos podem ser informados em Service Metadata URL / Metadata Connection Mode e estão disponíveis na solução criada.
  • A identidade do usuário (User’s Identity) será utilizada para conectar no serviço do WCF e consequentemente no banco de dados, por isso utilizamos Windows Authentication na conexão.

Após a criação da conexão é necessário criarmos as operações do CRUD para o ECT, etapa essa onde os métodos e parâmetros do Web Service serão mapeados. Para cada figura que mapeia um método temos tabelas que definem seus parâmetros de entrada e retorno (quando aplicados):

addcontact

Figura 6 - Operação AddContact

A operação AddContact da Figura 6 possui os seguintes parâmetros de entrada exibidos nas Tabelas 2 e 3:

Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Tabela 2 - Parâmetros de Entrada da Operação AddContact

Element Default Value Filter Element Path
ContactID <<None>>   contact.ContactID
Address <<None>>   contact.Address
City <<None>>   contact.City
CompanyName <<None>>   contact.CompanyName
ContactName <<None>>   contact.ContactName
ContactTitle <<None>>   contact.ContactTitle
Country <<None>>   contact.Country
Email <<None>>   contact.Email
Fax <<None>>   contact.Fax
Phone <<None>>   contact.Phone
PostalCode <<None>>   contact.PostalCode
Region <<None>>   contact.Region
Tabela 3 - Parâmetros de Entrada da Operação AddContact (Continuação)

Vale lembrar que nenhum parâmetro de retorno se aplica na operação AddContact, portanto simplesmente ignore a tela de configuração e finalize a criação do mapeamento.

deletecontact

Figura 7 - Operação DeleteContact

A operação DeleteContact da Figura 7 possui o seguinte parâmetro de entrada exibido na Tabela 4:

Element .NET Type Map to Identifier Identifier Display Name Default Value Filter Element Path
contactId System.Int32 TRUE ContactID ID <<None>>   contactId
Tabela 4 - Parâmetro de Entrada da Operação DeleteContact

getcontactbyid

Figura 8 - Operação GetContactById

A operação GetContactById da Figura 8 possui os seguintes parâmetros de entrada e retorno exibidos nas Tabelas 5, 6 e 7:

Element .NET Type Map to Identifier Identifier Display Name Default Value Filter Element Path
contactId System.Int32 TRUE ContactID ID <<None>>   contactId
Tabela 5 - Parâmetro de Entrada da Operação GetContactById

Data Source Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Tabela 6 - Parâmetro de Retorno da Operação GetContactById

Data Source Element Element Path Required Read-Only Office Property
ContactID GetContactById.ContactID FALSE TRUE Custom Property
Address GetContactById.Address FALSE FALSE Business Address (BusinessAddress)
City GetContactById.City FALSE FALSE Business Address City (BusinessAddressCity)
CompanyName GetContactById.CompanyName FALSE FALSE Company Name (CompanyName)
ContactName GetContactById.ContactName TRUE FALSE Full Name (FullName)
ContactTitle GetContactById.ContactTitle FALSE FALSE Title (Title)
Country GetContactById.Country FALSE FALSE Business Address Country/Region (BusinessAddressCountry)
Email GetContactById.Email TRUE FALSE Email 1 Address (Email1Address)
Fax GetContactById.Fax FALSE FALSE Business Fax Number (BusinessFaxNumber)
Phone GetContactById.Phone TRUE FALSE Business Telephone Number (BusinessTelephoneNumber)
PostalCode GetContactById.PostalCode FALSE FALSE Business Address Postal Code (BusinessAddressPostalCode)
Region GetContactById.Region FALSE FALSE Business Address State (BusinessAddressState)
Tabela 7 - Parâmetro de Retorno da Operação GetContactById (Continuação)

getcontacts

Figura 9 - Operação GetContacts

A operação GetContacts da Figura 9 não possui parâmetros de entrada a serem configurados, porém possui os seguintes parâmetros de retorno exibidos nas Tabelas 8 e 9:

Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Tabela 8 - Parâmetro de Retorno da Operação GetContacts

Element Element Path Required Read-Only Show in Picker Timestamp Field
ContactID GetContacts.GetContactsElement.ContactID FALSE TRUE FALSE FALSE
Address GetContacts.GetContactsElement.Address FALSE FALSE FALSE FALSE
City GetContacts.GetContactsElement.City FALSE FALSE FALSE FALSE
CompanyName GetContacts.GetContactsElement.CompanyName FALSE FALSE FALSE FALSE
ContactName GetContacts.GetContactsElement.ContactName TRUE FALSE FALSE FALSE
ContactTitle GetContacts.GetContactsElement.ContactTitle FALSE FALSE FALSE FALSE
Country GetContacts.GetContactsElement.Country FALSE FALSE FALSE FALSE
Email GetContacts.GetContactsElement.Email TRUE FALSE FALSE FALSE
Fax GetContacts.GetContactsElement.Fax FALSE FALSE FALSE FALSE
Phone GetContacts.GetContactsElement.Phone TRUE FALSE FALSE FALSE
PostalCode GetContacts.GetContactsElement.PostalCode FALSE FALSE FALSE FALSE
Region GetContacts.GetContactsElement.Region FALSE FALSE FALSE FALSE
Tabela 9 - Parâmetro de Retorno da Operação GetContacts (Continuação)

updatecontact

Figura 10 - Operação UpdateContact

A operação UpdateContact da Figura 10 possui os seguintes parâmetros de entrada exibidos nas Tabelas 10 e 11:

Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Tabela 10 - Parâmetros de Entrada da Operação UpdateContact

Element Default Value Filter Element Path
ContactID <<None>>   contact.ContactID
Address <<None>>   contact.Address
City <<None>>   contact.City
CompanyName <<None>>   contact.CompanyName
ContactName <<None>>   contact.ContactName
ContactTitle <<None>>   contact.ContactTitle
Country <<None>>   contact.Country
Email <<None>>   contact.Email
Fax <<None>>   contact.Fax
Phone <<None>>   contact.Phone
PostalCode <<None>>   contact.PostalCode
Region <<None>>   contact.Region
Tabela 11 - Parâmetros de Entrada da Operação UpdateContact (Continuação)

OBS: Reparem que na maior parte dos casos apenas a nomenclatura dos parâmetros de configuração (colunas) muda, porém os dados são os mesmos. Resolvi criar tabelas de configuração para cada operação no intuito de facilitar o mapeamento com operações separadas.

Uma vez que todas as colunas foram definidas, salve o ECT (1) e observe as operações criadas (2), as quais podem ser editadas a qualquer momento, conforme Figura 11:

savingECT

Figura 11 - Salvando o ECT

Nesse momento já é possível a criação de um External List que fará a interface visual com os dados externos no SharePoint 2010. Na mesma tela de External Content Types, visualize o menu de contexto (botão direito) e selecione a opção External List. Nomeie para “Contacts”, conforme Figura 12:

createECT

Figura 12 - Criação de um External List

Com a finalização da External List, chegamos ao propósito desse artigo. Cabe a você agora testar a External List, o que já foi explicado na Parte II do BCS. Reaproveite o mesmo teste e aplique aqui, pois ele foi criado para esse fim.

O fato de podermos utilizar um Web Service para a integração no SharePoint 2010 mostra que podemos conectar dados de qualquer sistema que disponibilize essa interface. Unifique os dados de diferentes sistemas no SharePoint 2010! Agora você sabe como fazê-lo!

Referência:
http://msdn.microsoft.com/en-us/library/ee556826(v=office.14).aspx

[]’s

Marcel Medina

Clique aqui para ler o mesmo conteúdo em Inglês.