December 2009

Volume 24 Number 12

SharePoint 2010 の Business Connectivity Services の使用

Kirk Evans | December 2009

私の子供たちが気に入っている本に、Laura Numeroff 著の『もしもねずみにクッキーをあげると』という 1 冊があります。これは、ドミノ倒しのように考え方が発展していくことを子供向けに示した本です。もし、ねずみにクッキーをあげると、ねずみはのどが渇いていることに気付いてミルクを欲しがります。ミルクを飲むと、鏡を欲しがり、次ははさみ、続いてほうき、今度はクレヨンという調子で、ねずみは現在持っている物の効用がわかると新しい物を欲しがります。

私の体験では、これこそ SharePoint の導入後に多くのユーザーが歩む道です。まず、ユーザーはそろそろとドキュメントをいくつかアップロードします。続いて、ワークフローやフォームを使用するようになり、最後にはサイト上に外部データを表示しようと考えます。ある作業をいかに簡単に達成できるかがわかるまで、次の課題に挑戦しようとは思わないものです。

よくあるシナリオとして、ポータルと外部データがあると、ユーザーはそのデータを意味のある方法でポータルに統合することを考えます。Microsoft Office SharePoint Server 2007 (MOSS 2007) でビジネス データ カタログ (BDC) が導入されたことで、まさにこのようなシナリオが容易になりました。つまり、外部データをポータルのページ内に簡単に表示できるようになったのです。たとえば、SharePoint と外部データのマッピングを定義する XML 定義ファイルを作成し、外部データを Web パーツとしてレンダリングして、リスト内の列として使用し、さらに検索に統合できます。

私が BDC を使用して既存の基幹業務 (LOB) アプリケーションにマッピングする方法を企業に紹介するとき、ようやく納得してもらえるようになるのは、たいてい私がユーザー、ドキュメント、リストのデータ、および既存の LOB システムのデータを (すべて同じ結果セット内に) 含む検索結果を示してからです。

MOSS 2007 の BDC を使用しても外部システムに接続できましたが、BDC にはデザイナーが用意されていなかったため、ソリューションを作成するのは困難でした。また、BDC ではビジネス データ リスト Web パーツにデータを表示するソリューションを、読み取り専用であればかなり容易に作成できましたが、ユーザーが変更したり、変更したデータを外部ストアに再度書き込んだりできるようにすることはそれほど簡単ではありませんでした。

SharePoint 2010 の Business Connectivity Services (BCS) は、外部データに接続することのみを目的としています。BCS は、外部データとサービスを密接に統合するソリューションの開発効率を上げるための機能、サービス、およびツールを既定で用意することにより、SharePoint プラットフォームの機能を強化しています。BCS はその前身である BDC を基盤として、プレゼンテーション、接続、ツール作成、およびライフサイクル管理という主要領域に対応しています。たとえば、SharePoint 2010 では、SharePoint Designer を使用して外部コンテンツ タイプを作成し、SharePoint の Web ユーザー インターフェイスに外部リストを作成し、このリストを Outlook にオフラインで取り込み、一連の連絡先とすることが簡単になります。また、Outlook で更新した連絡先を使って、外部システムのデータを更新することもできます。

BCS のアーキテクチャ

図 1 は、BCS を構成する主なコンポーネントを示しています。

Business Connectivity Services のアーキテクチャ

図 1 Business Connectivity Services のアーキテクチャ

  • BDC Metadata Store – BDC Metadata Store は、外部コンテンツ タイプのコレクション用に格納場所を提供します。各外部コンテンツ タイプには、それぞれ外部データへの接続方法が記述されます。Metadata Store は、サービス層の一部として機能します。外部コンテンツ タイプは、BCS の基盤となるビルド ブロックの 1 つです。
  • BDC Server Runtime – BDC Server Runtime は、バックエンド ストアにアクセスしてデータに接続する方法を、コンテンツ タイプのストア内に定義された外部コンテンツ タイプに基づいて認識します。BDC という頭字語が、BCS のコンポーネントへの接続を提供する一連のサービスを新たに表すようになったことに注意が必要です。
  • セキュリティ – BCS は、Secure Store Service (SSS) と統合され、独自のセキュリティ モデルを可能にします。
  • ソリューション パッケージ – BCS を使用して構築されたソリューションを Visual Studio Tools for Office (VSTO) パッケージにして、SharePoint Workspace、Outlook、Word などのリッチ クライアントに提供できます。BCS では、他のクライアントを対象とするようにソリューション パッケージを拡張する API も公開されます。
  • 組み込み UI – BCS では、外部データを Web パーツの UI から表示する機能をさらに押し進め、外部リストの追加によってさらに密接に統合できるようにしています。
  • BDC Client Runtime – クライアントとサーバーにそれぞれ対称的なランタイムを用意し、クライアント側キャッシュによりソリューションをオフラインで使用できるようにし、一貫性のある方法でサーバーに変更を反映できるようにしています。BDC Client Runtime を使用すると、外部データのキャッシュとやり取りするオフライン操作が可能になります。
  • デザイン ツール – SharePoint Designer には、外部コンテンツ タイプや外部リストを定義する機能、データを表示する InfoPath フォームを定義して単純なソリューションを作成する機能など、BCS ソリューションの作成機能が豊富に組み込まれています。プロの開発者は Visual Studio を使ってこのような機能を拡張し、既存のフレームワークを使用しながらも高度なソリューションを作成できるようになります。

BCS のアーキテクチャに加えられたこのような機能強化により、ビジネス インテリジェンス、エンタープライズ コンテンツの管理、グループ作業機能やソーシャル機能、エンタープライズ検索など、SharePoint プラットフォームの新たな機能を操作できるようになりました。さらに、BCS を使用することで、このような機能を簡単に使用するソリューションを作成できる、魅力的な開発プラットフォームが提供されます。

私が BCS を初めて目にしたとき、すぐに 2 つの点が目に付きました。1 点目は開発者の視点からのものですが、簡単に配布できるスマート クライアント ソリューションを通じて、驚くほど簡単に外部データをオフラインで使用できるようになったことです。これは、Microsoft .NET Framework の ClickOnce 機能を使用する VSTO アドインが生成されるためです。2 つ目の非常に印象的な点は、SQL Server Compact Edition を永続的なストアとして使用するクライアント側キャッシュが組み込まれたことで、クライアント側ソリューションと外部システムとの間で変更を同期できるようになったことです。実績があり、広く採用されているテクノロジが使用されているため、開発者は BCS の信頼性が高いことを強く感じるでしょう。

BCS が実質的に提供している機能が、外部データの接続、そのデータを操作する対称的なクライアントとサーバーのランタイム、およびスマート クライアント アプリケーションによる BCS ソリューションのパッケージ化だということがわかれば、既存のシステムと統合してエンド ユーザーに豊富な機能を提供できるソリューションをすぐに理解できます。

また、前身の BDC に精通していれば、BCS には単なるデータ接続にとどまらないシナリオが含まれているため、開発者にとっては、ソリューションを可能にするための非常に魅力的な選択肢になることがはっきりとわかるでしょう。ここからは、外部コンテンツ タイプの作成と、BCS のオフライン機能について詳しく説明します。

外部コンテンツ タイプについて

外部コンテンツ タイプは BCS に不可欠な概念です。コンテンツ タイプの概念は Windows SharePoint Services 3 で導入され、リスト向けに再利用可能なスキーマを記述していました。外部コンテンツ タイプはこの概念を拡張し、外部システムのスキーマだけでなく、外部システムのデータ アクセス機能や Office と SharePoint での動作も記述するようになります。外部コンテンツ タイプは、データ ソースのエンティティと動作の両方を示す、SharePoint と外部システムの間のマッピングと考えることができます。

外部コンテンツ タイプは、XML 文法で記述したメタデータを使用して定義し、BDC Metadata Store に配置します。MOSS 2007 の BDC に詳しい方のために説明すると、この概念は以前 BDC エンティティと呼ばれていましたが、SharePoint および Office での外部コンテンツの動作も含むように拡張されています。

SharePoint Designer 2010 には、外部コンテンツ タイプをすばやく作成し、作成した外部コンテンツ タイプに基づいて外部リストを作成する簡単なインターフェイスが備わっています。Visual Studio を使用して外部コンテンツ タイプを作成する理由は、SharePoint Designer 2010 に組み込まれていない機能を使用する必要が生じることがあるためです。カスタム外部コンテンツ タイプを作成すると、同じ外部システムを複数回呼び出す、複数の外部システムを複数回呼び出す、ある外部システムから読み取って別の外部システムに書き込む、といった集計シナリオに役立ちます。また、外部システムのデータ形式と SharePoint でのデータの表示方法との間に明確なマッピングが存在しない複雑な変換を行う場合にも、カスタム外部コンテンツを作成しておくと便利です。カスタム セキュリティ コードを実装する場合や、複雑なバックエンド システムとのやり取りに必要なカスタム ビジネス ロジックを実装する場合も、カスタム外部コンテンツが有効です。

IT プロフェッショナルは SharePoint Designer 2010 を使用して、SQL Server、Windows Communication Foundation (WCF) サービス、または .NET 型との間でデータを読み書きする外部コンテンツ タイプを作成できます。これにより、開発者が公開しているソースのデータを利用する簡単なソリューションをすばやく作成できます。たとえば、IT プロフェッショナルは SharePoint Designer 2010 を開いて、左側のナビゲーション ウィンドウで [External Content Types] (外部コンテンツ タイプ) をクリックします。次にリボンの [New External Content Type] (新しい外部コンテンツ タイプ) をクリックし、[Click here to discover external data sources and define operations] (外部データ ソースを見つけて操作を定義するにはここをクリックします) リンクをクリックします。表示される [Operation Designer] (操作デザイナー) ダイアログ ボックスでは、データベース テーブルへの接続を追加できます。続いて、テーブルを右クリックして [Create All Operations] (すべての操作を作成) をクリックし、読み取り、1 つのレコードの選択、更新、およびデータベース テーブルの行の削除 (もちろん操作に適した資格情報がある場合) を実行するメソッドを作成します。このようすを図 2 に示します。

SharePoint Designer 2010 を使用した操作の作成

図 2 SharePoint Designer 2010 を使用した操作の作成

外部コンテンツ タイプとは、実際には外部データを再利用可能にするための記述で、次のような複数のアプリケーションにまたがって外部データをネイティブな Office エンティティとして操作できるようにします。

  • 外部リストとしての SharePoint
  • Outlook
  • SharePoint Workspace
  • Word
  • InfoPath
  • Access
  • コードを使用するその他の Office アプリケーション

これは非常に強力な機能で、ナレッジ ワーカーであれば、SharePoint 外のシステムに接続して、何種類ものクライアント アプリケーションで読み書き可能な形式でデータを表示できます。開発者であれば、複数ソースからのデータの集計、複雑な変換機能の提供、複雑なビジネス ロジックやカスタムのセキュリティ要件の評価、データを 1 つのビューで提供するためのシステムの複数回の呼び出しなど、SharePoint Designer 2010 だけでは不可能な複雑な操作を実行するソリューションを提供してナレッジ ワーカーを支援するという、非常に興味深いチャンスが得られます。

BCS のフレームワークを使用して作業したり、BCS に関するさまざまなドキュメントや記事を読むと、おそらく "外部コンテンツ タイプ" と "エンティティ" という用語があいまいに使用されていることに気付くでしょう。この 2 つの用語の意味はまったく同じです。"エンティティ" という用語は、SharePoint 2007 の環境で使用されていました。ランタイム API レベルではまだ使用されています。"エンティティ" は一般に開発者を対象とする環境で使用されます。一方、"外部コンテンツ タイプ" は、SharePoint Designer 2010 など複数のユーザーを対象とする環境で使用されます。ツールやドキュメントで "外部コンテンツ タイプ" と "エンティティ" というの使い方が置き換わっていても、混乱しないでください。

Visual Studio 2010 でエンティティを作成する

開発者の視点から外部コンテンツ タイプの役割について理解を深めるために、集計シナリオを見てみましょう。顧客に関するデータを公開する RESTful サービスの例として、Twitter API を使用します。また、最終購入日、最終購入量といった、顧客に関する詳細情報を含む、カスタマー リレーションシップ マネジメント (CRM) システムを模したカスタム データベースを使用します。これら 2 つの外部ソースからのデータを集計して、ユーザーが外部ソースを意識することなく、SharePoint リストに表示します。

Visual Studio 2010 の [New Project] (新しいプロジェクト) ダイアログ ボックスで、[Business Data Connectivity Model] (Business Data Connectivity モデル) を選択し、"Msdn.Samples.BCS" というプロジェクト名を付けます。新しいプロジェクトのウィザードで、デバッグに使用する SharePoint サイトを選択するよう求められます。最後に、Visual Studio 2010 によって、エンティティ、エンティティ サービス、モデル定義、および Visual Studio のデザイン サーフェイスをサポートするために使用されるダイアグラム ファイルのスタブ コードが作成されます。

Entity1.cs ファイルにはエンティティのスキーマが記述され、パブリック プロパティを持つ通常のクラスとしてモデル化されます。Entity1Service.cs ファイルでは CRUD (作成、読み取り、更新、および削除) の各メソッドが用意されます。このうち 2 つのメソッドがサンプルとして作成されます。作成される 1 つ目のメソッドは、識別子に基づいて外部ストアの特定のレコードを取得する ReadItem です。このメソッドは、SpecificFinder 型のメソッド インスタンスとして XML メタデータにマッピングされます。作成される 2 つ目のメソッドは外部ストアのすべてのレコードを取得する ReadList です。このメソッドは、Finder 型のメソッド インスタンスとして XML メタデータにマッピングされます。この 2 つのメソッドが、BCS のコネクターとして機能するためにエンティティに実装する必要がある最低限のメソッドです。

エンティティをモデル化する

最初に、エンティティ自体を変更しましょう。Entity クラスを図 3 に示すコードに置き換えます。

図 3 Entity クラスを置き換えるコード

namespace Msdn.Samples.BCS.SocialModel
{    
public partial class Customer
    {        
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }        


//Twitter specific properties
public string TwitterScreenName { get; set; }             
public string TwitterStatus { get; set; }

//CRM specific properties
public DateTime DateLastPurchase { get; set; }
public decimal AmountLastPurchase { get; set; }
    }
}

ソリューション エクスプローラーで .bdcm ファイルを開き、コードを置き換えてからエンティティのデザイン サーフェイスに戻ると、デザイン サーフェイスのエンティティは影響を受けていないことがわかります。デザイン サーフェイスのエンティティはメタデータを表します。SharePoint で想定されているコードとメタデータの間になんらかのマッピングを設定するかどうかは自由です。モデルのデザイン サーフェイスで、エンティティ名を Customer に変更します。次に、Identifier1 エンティティ識別子をクリックして、CustomerID という名前に変更し、型を System.Int32 型に変更します。これで、Customer エンティティに CustomerID という整数識別子が設定されること、およびこのエンティティが Customer クラスにマッピングされることを SharePoint に通知しました。

メソッドをモデル化する

エンティティをモデル化したので、次はエンティティのメソッドをモデル化する必要があります。既に説明したように、Visual Studio では、最低限の機能を提供する ReadItem と ReadList という 2 つのメソッドが作成されます。先に [BDC Method Details] (BDC メソッドの詳細) ウィンドウでメソッドを 2 つとも削除してから、目的の名前の新しいメソッドを代わりに作成する方が簡単でしょう。このようにすると、白紙の状態から、マッピングが実行されるようすを確認できます。そのためには、[BDC Method Details] (BDC メソッドの詳細) ウィンドウを開き、[ReadList] (ReadList) メソッド、[delete] (削除) ボタンの順にクリックします。ReadItem メソッドについても同様に操作します。ただし、私の経験では、これらの操作をエンティティ デザイナー自体では実行しないで、できる限り [BDC Method Details] (BDC メソッドの詳細) ウィンドウまたは BDC Explorer (BDC エクスプローラー) を使用して慎重に編集することをお勧めします。

まず、SpecificFinder メソッドをモデル化します。このメソッドは SharePoint でリスト内のすべてのアイテムのリストを取得するのに使用されます。白紙の状態から作業するため、[BDC Method Details] (BDC メソッドの詳細) ウィンドウの [<Add a Method>] (<メソッドの追加>) というテキストをクリックします。このテキストをクリックするとドロップダウン矢印が表示され、この矢印をクリックすると、作成するメソッドの種類が一覧表示されます。[Create Specific Finder Method] (固有の検索メソッドの作成) オプションを選択すると、ReadItem というメソッド、メソッドのパラメーター、およびメソッド インスタンスが作成されます。同じウィンドウに [Name] (名前)、[Direction] (方向)、および [Type Descriptor] (型記述子) という 3 つの列があり、戻り値パラメーターに Customer という型記述子があることに注目してください。[Customer] (Customer) 型記述子をクリックして [Properties] (プロパティ) ウィンドウを確認すると、Type Name プロパティの値が現在 System.String であることがわかります。前のセクションで作成した新しい Customer 型を返すことを SharePoint に通知する必要があるため、この値を "Msdn.Samples.BCS.Customer, Msdn.Samples.BCS" に変更します。

ここで、BDC Explorer (BDC エクスプローラー) ウィンドウについて説明しましょう。このウィンドウには、モデル、エンティティ、およびメソッドが階層形式で表示されます。ReadItem メソッドを展開すると、customer パラメーターが表示され、その下に型記述子を表す Customer という子ノードが表示されます。他にも型記述子を子ノードとして追加し、複合型を表す必要があります。この操作は簡単です。BDC Explorer (BDC エクスプローラー) で [Customer] (Customer) 型記述子を右クリックし、[Add Type Descriptor] (型記述子の追加) をクリックします。型記述子の名前を CustomerID に、型を System.Int32 に変更します。同じ手順を繰り返して、前のセクションで作成した Customer クラスを反映するよう適切な名前と型の型記述子を追加します。すべての型記述子を作成したら、[CustomerID] (CustomerID) 型記述子をクリックし、Identifier プロパティを CustomerID に、Read-only プロパティを True に設定します。最終的に、図 4 のような状態になります。

BDC Explorer (BDC エクスプローラー) ウィンドウを使用した TypeDescriptor のプロパティの設定

図 4 BDC Explorer (BDC エクスプローラー) ウィンドウを使用した TypeDescriptor のプロパティの設定

次の手順は、顧客のリスト全体を返すメソッドの作成です。Customer 型とその型記述子の定義は既に完了しているので、次の手順は簡単です。[BDC Method Details] (BDC メソッドの詳細) ウィンドウに戻り、[<Add a Method>] (<メソッドの追加>) というテキストをクリックして、[Create Finder Method] (検索メソッドの作成) オプションを選択します。ReadList という新しいメソッドが作成されます。このメソッドの型は Customer オブジェクトのジェネリック リストです。また、型記述子が定義済みなので、次はこれらのメソッドの実装に注目しましょう。

メソッドを実装する

このシナリオでは、オンライン ソース (Twitter) と専用のストア (SQL Server データベース) からデータを集計する必要があります。ここでは、Twitter のデータの取得と Customer エンティティ型への格納に役立つように、TwitterHelper というヘルパー クラスを実装しました。GetChannelWithCredentials メソッドを使用すると、WCF と WCF の Web プログラミング機能を使用して、特定の組み合わせの資格情報を使用する Twitter を簡単に呼び出すことができます。GetCustomersFromTwitter メソッドは、ユーザーとその現在状態のリストを返し、Customer オブジェクトのリストにデータを格納します。GetCustomerFromTwitterByScreenName メソッドは、ユーザーの画面名に基づいて Twitter から 1 人のユーザーを取得し、そのデータを 1 つの Customer オブジェクトに返します。TwitterHelper のコードを図 5 に示します。

図 5 TwitterHelper クラス

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Channels;
using System.Xml.Linq;

namespace Msdn.Samples.BCS.SocialModel
{
    [ServiceContract]
public interface ITwitterFriends
    {
        [OperationContract]
        [WebGet(UriTemplate="/statuses/friends.xml")]
        Message GetAllFriends();

        [OperationContract]
        [WebGet(UriTemplate = "/users/show.xml?screen_name={screenName}")]
        Message GetFriendByID(string screenName);

    }

public class TwitterHelper
    {
public static List<Customer> GetCustomersFromTwitter()
        {
var cf = GetChannelWithCredentials();

using(cf)
            {
                ITwitterFriends proxy = cf.CreateChannel();
                Message m = proxy.GetAllFriends();

List<Customer> customers =
                        (from user in XDocument.Load(m.GetReaderAtBodyContents()).Root.Elements("user")
select new Customer
                         {
                             TwitterScreenName = user.Element("screen_name").Value, 
                             TwitterStatus = user.Element("status").Element("text").Value
                         }).ToList();

return customers;
            }
        }

public static Customer GetCustomerFromTwitterByScreenName(string screenName)
        {
var cf = GetChannelWithCredentials();

using (cf)
            {

                ITwitterFriends proxy = cf.CreateChannel();
                Message m = proxy.GetFriendByID(screenName);

                XElement user = XDocument.Load(m.GetReaderAtBodyContents()).Root;

                Customer c = new Customer
                {
                    TwitterScreenName = user.Element("screen_name").Value,                    
                    TwitterStatus = user.Element("status").Element("text").Value
                };

return c;
            }
        }

private static WebChannelFactory<ITwitterFriends> GetChannelWithCredentials()
        {
            WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
            binding.MaxReceivedMessageSize = 999999;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
            binding.Security.Transport.Realm = "Twitter API";

            Uri location = new Uri("http://www.twitter.com");
            WebChannelFactory<ITwitterFriends> cf = new WebChannelFactory<ITwitterFriends>(binding, location);
            cf.Credentials.UserName.UserName = "your_twitter_screenname_here";
            cf.Credentials.UserName.Password = "your_password_here";

return cf;
        }

    }
}

ここで使用するデータベース テーブルは非常に単純です。以下にデータベース テーブルのスキーマを示します。

CREATE TABLE [dbo].[Customer](
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[TwitterScreenName] [nvarchar](100) NOT NULL,
[DateLastPurchase] [date] NOT NULL,
[AmountLastPurchase] [decimal](18,0) NOT NULL)

データを簡単に照会できるよう、ここでは LINQ to SQL クラスをプロジェクトに追加し、Customer データベース テーブルをポイントして dbml ファイルを生成しました。1 つ目の GetCustomer メソッドでは、LINQ to SQL を使用してデータベースに 1 件の顧客レコードを照会し、そのユーザーの現在状態を Twitter から取得します。GetCustomer メソッドと GetCustomerList メソッドの詳細を図 6 に示します。最後に、F5 キーを押して、外部コンテンツ タイプを配置し、デバッグを開始します。ブレークポイントをコードに設定してすべてが正常に機能していることを確認できるようにします。

図 6 GetCustomer メソッドと GetCustomerList メソッド

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Msdn.Samples.BCS.SocialModel
{
public partial class CustomerService
    {
private const string CONNECTION_STRING = @"Data Source=moss2010demo\sqlserver;Initial Catalog=CustomerCRM;Integrated Security=True";

public static Customer GetCustomer(int customerID)
        {            
//Pull from database, then pull from Twitter
using (CustomerCRMDataContext db = new CustomerCRMDataContext(CONNECTION_STRING))
            {
                Customer customer = (from c in db.Customers
where c.CustomerID == customerID
select new Customer
                     {
                         CustomerID = c.CustomerID,
                         FirstName = c.FirstName,
                         LastName = c.LastName,
                         AmountLastPurchase = c.AmountLastPurchase,
                         DateLastPurchase = c.DateLastPurchase,
                         TwitterScreenName = c.TwitterScreenName
                     }).FirstOrDefault();

                Customer friend = TwitterHelper.GetCustomerFromTwitterByScreenName(customer.TwitterScreenName);
                customer.TwitterStatus = friend.TwitterStatus;                
return customer;
            };

        }

public static IEnumerable<Customer> GetCustomerList()
        {
//Pull all friends from Twitter, 
// then only return friends that also have CRM records
List<Customer> friends = TwitterHelper.GetCustomersFromTwitter();

List<Customer> customers = new List<Customer>();

using (CustomerCRMDataContext db = new CustomerCRMDataContext(CONNECTION_STRING))
            {
foreach (Customer friend in friends)
                {
var cust = db.Customers.FirstOrDefault(c => c.TwitterScreenName == friend.TwitterScreenName);
if (null != cust)
                    {
                        customers.Add(new Customer
                        {
                            CustomerID = cust.CustomerID,
                            FirstName = cust.FirstName,
                            LastName = cust.LastName,
                            AmountLastPurchase = cust.AmountLastPurchase,
                            DateLastPurchase = cust.DateLastPurchase,
                            TwitterScreenName = cust.TwitterScreenName,
                            TwitterStatus = friend.TwitterStatus
                        });
                    }
                }
return customers;
            };                        
        }

    }
}

既に述べたように、BCS の興味深い点の 1 つは、オフライン クライアントで行った変更を、外部のデータ ストアと同期して反映する機能です。この機能を追加するには、Updater メソッドを実装します。これには、新しい Updater メソッドを [BDC Method Details] (BDC メソッドの詳細) ウィンドウに追加するだけです。Updater メソッド本体は、図 7 のようになります。

図 7 変更を同期する Update メソッド

public static void Update(Customer customer)
{
//Update only the CRM database information
using (CustomerCRMDataContext db = new CustomerCRMDataContext(CONNECTION_STRING))
    {
var cust = db.Customers.Single(c => c.CustomerID == customer.CustomerID);
    cust.AmountLastPurchase = customer.AmountLastPurchase;
    cust.DateLastPurchase = customer.DateLastPurchase;
    db.SubmitChanges();
    };
}

このように、Visual Studio 2010 のツールを使用すると、書き込み可能な外部コンテンツ タイプの作成が非常に簡単になります。

リストを作成してオフラインで使用する

ここまでの手順は外部コンテンツ タイプを作成しただけです。外部コンテンツ タイプのインスタンスを表すリストはまだ作成していません。前の手順で F5 キーを押して外部コンテンツ タイプを配置したので、デバッガーにアタッチされた SharePoint サイトが表示されていると思います。画面の左上にある [Site Actions] (サイトの操作) メニューの [View All Site Content] (すべてのサイト コンテンツの表示) オプションをクリックします。viewlsts.aspx ページが表示されたら、[Create] (作成) リンクをクリックします。その結果、さまざまなタイプのコンテンツを作成できる新しいダイアログ ボックスが表示されます。一連のインストール済み項目から [External List] (外部リスト) を選択し、[Create] (作成) ボタンをクリックします。表示されるページで、[Name] (名前) ボックスに新しいリストの名前を指定し、既存の外部コンテンツ タイプを一覧から選択します (図 8 参照)。

外部コンテンツ タイプを使用したリストの作成

図 8 外部コンテンツ タイプを使用したリストの作成

[Create] (作成) ボタンをクリックすると、ついに SharePoint のリストが表示されます。このリストには、これまでの作業の成果がデータのリストとして SharePoint に表示されます (図 9 参照)。

外部コンテンツ タイプを使用して構築されたリスト

図 9 外部コンテンツ タイプを使用して構築されたリスト

リストをオフラインで使用する

SharePoint 2010 の外部接続に関して大きく強化された点の 1 つが、リストをオフラインで使用してデータを同期する機能です。次の手順では、SharePoint Designer 2010 を開いて、外部コンテンツ タイプ ソリューションを作成する際にどのように開発者と IT プロフェッショナルの役割が連携するかについて説明します。

冒頭で触れたように、ナレッジ ワーカーは SharePoint Designer 2010 を使用して、外部コンテンツ タイプを作成および使用できます。まず、SharePoint Designer 2010 で SharePoint サイトを開き、ナビゲーション ウィンドウの [External Content Types] (外部コンテンツ タイプ) リンクをクリックします。選択できる外部コンテンツ タイプの 1 つとして、Msdn.Samples.BCS.SocialModel.Customer コンテンツ タイプが表示されます。このリンクをクリックすると、外部コンテンツ タイプのサマリー ビューが表示されます。このページでは、メタデータで定義してコードで実装したメソッドを表示できます。

このページの [External Content Type Information] (外部コンテンツ タイプの情報) セクションには、Office Item Type (Office アイテム タイプ) を指定するドロップダウン リストが表示されます。このドロップダウン リストをクリックすると、次のオプションが表示されます。

  • Generic List (ジェネリック リスト)
  • Appointment (予定)
  • Contact (連絡先)
  • Task (タスク)
  • Post (投稿)

このリストを使用すると、外部コンテンツ タイプのデータをこれらのいずれかの Office Item Type (Office アイテム タイプ) として表示できますが、選択したタイプによってデータの表示方法と同期方法が変わります。たとえば、Contact (連絡先) というタイプを選択すると、Outlook にリストをオフラインで取り込み、連絡先のリストとして表示できます。同様に、予定表アイテムのようなデータは、Outlook の予定としてモデル化できます。これにより、SharePoint データのオフライン クライアントとして Outlook が密接に統合されます。さらに、更新したデータを外部データ ソースと同期を取って反映する機能も提供されます。データを Outlook の連絡先としてマッピングするには、[Office Item Type] (Office アイテム タイプ) ボックスの一覧で [Contact] (連絡先) をクリックします。タイプを選択すると、マッピングが正しくないことを示す警告が新しく表示されます。GetCustomer メソッドをダブルクリックして、マッピングのダイアログ ボックスを表示します。[Return Parameter Configuration] (戻り値パラメーターの構成) 画面が表示されるまで、[Next] (次へ) をクリックします。Contact タイプのマッピングの最小要件は、姓のパラメーターをマッピングすることです。マッピングするには、[Data Source Elements] (データ ソース要素) ツリー ビューの LastName プロパティをクリックし、右側の [Office Property] (Office プロパティ) の値を LastName プロパティに変更します。この画面で、FirstName プロパティも FirstName という Office プロパティにマッピングします。図 10 にこの結果を示します。

データ ソース要素と Office プロパティのマッピング

図 10 データ ソース要素と Office プロパティのマッピング

Office のタイプへのマッピングを指定したら、SharePoint の Web UI に戻って、リボン UI の [Lists] (リスト) をクリックし、[Connect to Outlook] (Outlook に接続) を選択します。このようにすることで、SharePoint に対し、このリストの VSTO パッケージを作成して、Outlook アドインとしてローカルのデスクトップにインストールするよう要求します (図 11 参照)。

ClickOnce の使用により提供される外部コンテンツ タイプのオフライン エクスペリエンス

図 11 ClickOnce の使用により提供される外部コンテンツ タイプのオフライン エクスペリエンス

VSTO パッケージがインストールされると、エンド ユーザーは Outlook の他の連絡先アイテムと同様に連絡先アイテムを開くことができます。また、姓と名のプロパティが適切にマッピングされています (図 12)。

外部エンティティのデータに Outlook でアクセスでき、カスタム フィールド データが下部のウィンドウに保持されているようす

図 12 外部エンティティのデータに Outlook でアクセスでき、カスタム フィールド データが下部のウィンドウに保持されているようす

さらに、付加的なデータも連絡先のフォームに保持されて表示されるので、簡単にこの画面でデータを更新してローカル キャッシュに保存し、後で外部システムと同期できます。この VSTO パッケージは ClickOnce を使用して配置されるので、Windows の [プログラムの追加と削除] ダイアログ ボックスを使用したアドインのアンインストールなど、ClickOnce テクノロジを使用する場合と同じメリットを得られます。

無限の可能性

SharePoint 2010 の BCS 機能は非常に多く、このテーマで本 1 冊をたやすく書けるほどです。この記事で紹介するトピックを絞り込むのには苦労しました。多数のトピックを紹介しましたが、多くの他の領域は取り上げることすらできませんでした。たとえば、InfoPath を使用して SharePoint Workspace に表示される独自のフォームの提供、BDC Client Runtime 経由の BCS データへのアクセス、独自の VSTO アドインを開発して BCS 機能を Excel 2010 で使用できるようにする方法、BCS とクレームベースのセキュリティの併用、Secure Store Service との統合などが挙げられます。

BCS には非常に大きな可能性があるため、今後数年間にわたって BCS が多数の記事や書籍で取り上げられるのは間違いありません。ねずみにクッキーをあげたのと同様に、BCS を使い始めたら、この魅力的なテクノロジを使用して次から次へとやりたいことが思い浮かぶでしょう。

Kirk Evans * は、マイクロソフトの通信部門の事務所に所属する業務アーキテクトです。大手メディア企業、電気通信企業、出版社、および広告代理店と協力して、業界固有のソリューションを作成しています。彼のブログは、blogs.msdn.com/kaevans (英語) で公開されています。*

この記事のレビューに協力してくれた技術スタッフの Lionel Robinson と Brad Stevenson に心より感謝いたします。