[SharePoint 2010 開発] Visual Studio による Business Connectivity Services (BCS) の外部リスト (External List) 作成

環境 :
SharePoint Server 2010 (Beta 2) ※現Betaでは、SharePoint Foundation 上では動作しません !
Visual Studio 2010 (Beta 2)

<<SharePoint 2010 開発 新機能>>

こんにちは。

少し間があいてしまいましたが (すみません、いろいろとやることが多く . . .)、セッションでコードとデモ (実行結果) だけお見せしたビジネスコネクティビティサービス (BCS) を使用したエンティティの実装方法について説明します。
セッションでご説明したとおり、この機能は、SharePoint Designer 2010 を使用して、データベースや WCF サービスなどのバックエンドデータにノンコードで (現場の管理者・利用者が) 接続できるという点がメリットであり、ここでご紹介する Visual Studio 2010 を使用したエンティティ作成は開発者 (プロ・デベロッパー) 向けの手段であるという点に注意してください。

ちょうど時を同じくして、SharePoint チームブログ からも同様の紹介がおこなわれていますので参考になります。ただ、ここでは、デモでもお見せした Update (更新) もおこなう外部リストと、関連するコードなどもあわせてご紹介していきたいと思います。 (と言いますか、セッションでは説明できなかったそうした部分を説明するのが目的です。)

すみません、環境上の事情があり、英語環境を使用していますが、特に深い意味はございません。。。

外部リストの編集

まず、Visual Studio 2010 を起動し、[Business Data Connectivity Model] のプロジェクトを新規作成します。
プロジェクトの BcsModel1.bdcm をクリックすると、セッションでもお見せしたように以下のようなデザイナーが表示されます。

内部の仕組みを理解していただくため、試しに BdcModel1.bdcm を右クリックして [Open with …] メニューを選択し、XML エディターでこのファイルを開いてみましょう。すると、SharePoint Server 2007 でおなじみの以下の BDC (ビジネスデータカタログ) と同様の定義が表示されます。
そうなんです!セッションでもご説明した通り、BCS は実は過去の BDC の上に構築されていますので、エンティティフレームワークのデザイナーのように見えますが、実際には BDC の知識が必要となります。

<?xml version=”1.0″ encoding=”utf-8″?>
<Model xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns:xsd=”http://www.w3.org/2001/XMLSchema&#8221; xmlns=”http://schemas.microsoft.com/windows/2007/BusinessDataCatalog&#8221; Name=”BdcModel1″>
  <LobSystems>
    <LobSystem Name=”BdcModel1″ Type=”DotNetAssembly”>
      <LobSystemInstances>
        <LobSystemInstance Name=”BdcModel1″ />
      </LobSystemInstances>
      <Entities>
        <Entity Name=”Entity1″ Namespace=”BdcModelProject1.BdcModel1″ EstimatedInstanceCount=”1000″ Version=”1.0.0.0″>
          <Properties>
            <Property Name=”Class” Type=”System.String”>BdcModelProject1.BdcModel1.Entity1Service, BdcModel1</Property>
          </Properties>
          <Identifiers>
            <Identifier Name=”Identifier1″ TypeName=”System.String” />
            <!– TODO:change the name of the ID and if needed the TypeName of your identifier.–>
          </Identifiers>
          <Methods>
            <!– start finder method–>
            <Method Name=”ReadList”>
              <!– TODO:change the name of the method if needed.–>
              <Parameters>
                <Parameter Direction=”Return” Name=”returnParameter”>
                  <TypeDescriptor TypeName=”System.Collections.Generic.IEnumerable`1[[BdcModelProject1.BdcModel1.Entity1, BdcModel1]]” IsCollection=”true” Name=”Entity1List”>
                    <TypeDescriptors>
                      <TypeDescriptor TypeName=”BdcModelProject1.BdcModel1.Entity1, BdcModel1″ Name=”Entity1″>
                        <TypeDescriptors>
                          <TypeDescriptor TypeName=”System.String” IdentifierName=”Identifier1″ Name=”Identifier1″ />
                          <TypeDescriptor TypeName=”System.String” Name=”Message” />
                          <!– TODO: add typedescriptors when you add properties to Entity1.–>
                        </TypeDescriptors>
                      </TypeDescriptor>
                    </TypeDescriptors>
                  </TypeDescriptor>
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Type=”Finder” ReturnParameterName=”returnParameter” Default=”true” Name=”ReadList” DefaultDisplayName=”Entity1 List” />
              </MethodInstances>
            </Method>
            <!– end finder method–>
            <!– start specific finder method–>
            <Method Name=”ReadItem”>
              <Parameters>
                <Parameter Direction=”In” Name=”id”>
                  <TypeDescriptor TypeName=”System.String” IdentifierName=”Identifier1″ Name=”Identifier1″ />
                </Parameter>
                <Parameter Direction=”Return” Name=”returnParameter”>
                  <TypeDescriptor TypeName=”BdcModelProject1.BdcModel1.Entity1, BdcModel1″ Name=”Entity1″>
                    <TypeDescriptors>
                      <TypeDescriptor TypeName=”System.String” IdentifierName=”Identifier1″ Name=”Identifier1″ />
                      <TypeDescriptor TypeName=”System.String” Name=”Message” />
                      <!– TODO: add typedescriptors when you add properties to entity1.–>
                    </TypeDescriptors>
                  </TypeDescriptor>
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Type=”SpecificFinder” ReturnParameterName=”returnParameter” Default=”true” Name=”ReadItem” DefaultDisplayName=”Read Entity1″ />
              </MethodInstances>
            </Method>
            <!– end specific finder method–>
          </Methods>
        </Entity>
      </Entities>
    </LobSystem>
  </LobSystems>
</Model>

では、この BdcModel1.bdcm を閉じて、再度ダブルクリックをしてデザイナーで編集していきましょう。

新規作成されたプロジェクトには、実は、既に必要な設定のかなりの部分が作成されています (このまま配置をしてしまっても動きます)。たとえば、デザイナーの下部に表示されている [BDC Model Details] ウィンドウで、[ReadItem] – [Instances] – [ReadItem] を選択してプロパティウィンドウを見ると、メソッドの Type プロパティとして、SharePoint 2007 時代の BDC で「単一アイテムの取得」を意味していた「SpecificFinder」が設定されているのがわかります。

また、プロジェクトの Entity1.cs、Entity1Service.cs のコードを表示すると、既に、ダミーの Entity1 クラスと、ReadItem メソッド、ReadList メソッドが記入されていることがわかります。

public partial class Entity1
{
    public string Identifier1 { get; set; }
    public string Message { get; set; }
}

. . .(省略)

では、いろいろと名称などを変更して試してみましょう。

例えば、デザイナー (一番先頭の図を参照) の上で、「Entity1」を「Product」に名称変更し、ReadItem などでアイテムを特定するための「Identifier1」を「ProductIdentifier」と名称変更してみましょう。すると、これらを使用している他の箇所も自動的に名称が変更 (リファクタリング) されます。(BdcModel1.bdcm を上述のように XML として表示するとよくわかります。) 同様にしてメソッド名などもデザイナー上から変更できます。

ソリューションエクスプローラ上で、Entity1.cs のファイル名を ProductEntity1.cs に変更します。(クラス名も変更され、すべての参照を変更するか確認されるので [Yes] ボタンを押します。) BdcModel1.bdcm を表示して、右に表示される [BDC Explorer] (下図) で Entity1 を選択してプロパティウィンドウを確認すると、Entity1 の型 (クラス) も「Entity1」から「ProductEntity」に変更されているのがわかります。

では、ProductEntity クラスのプロパティを変更・追加してみましょう (ここは少し面倒です)。

ProductEntity.cs を開いて、以下の通り記述してみます。(もともとは、上述した Entity1 クラスのような定義になっています。下記で ProductId と ProductName は変更したプロパティで、ProductCost は今回追加したプロパティです。)

public partial class ProductEntity
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public int ProductCost { get; set; }
}

残念ながら、このプロパティの変更は BdcModel1.bdcm にはまったく反映 (リファクタリング) されません。(独自に作成されている .NET のクラスなので、まあ当然と言えば当然かもしれません。。。) 以降は、上記のプロパティの変更・追加にあわせて、上述した [BDC Explorer] を使用して、以下の手順でモデルに反映させていきます。

  • [BDC Explorer] で、BdcModel1 – Product – ReadItem – id – Identifier1 を選択し、Name プロパティを「Identifer1」から「ProductId」に変更しておきます。(必要があれば Type Name も変更しますが、今回は同じ String 型なので変更しなくても OK です。)
  • BdcModel1 – Product – ReadItem – returnParameter – Entity1 – Identifer1 も同様に Name を「ProductId」に変更します。
  • BdcModel1 – Product – ReadItem – returnParameter – Entity1 – Message も同様に Name を「ProductName」に変更します。
  • つぎに、ProductCost を追加します。BdcModel1 – Product – ReadItem – returnParameter – Entity1 を右クリックし、[Add Type Descriptor] を選択して TypeDescriptor を追加し、[Name] を「ProductCost」、[Type Name] を「System.Int32」に設定します。
  • 以降は省略しますが、BdcModel1 – Product – ReadList 以下も同様に変更をしておきます。(なお、面倒な場合には、先ほどの BdcModel1 – Product – ReadItem – returnParameter – Entity1 ごとコピー/ペーストできます。)

以上でモデルの変更は完了です。 

つぎに、ReadItem メソッドや ReadList メソッドなどのプログラムが記述されている ProductService.cs (もともと、Entity1Service.cs だったもの) のコードを表示し、以下の通りコードを記述します。今回は、Dictionary 型のクラスを作成して ProductEntity の一覧情報を格納し、ReadItem メソッドでは渡された Identifier をもとに該当の ProductEntity を渡し、ReadList では Dictionary の ProductEntity の一覧をそのまま渡すように実装します。

public static Dictionary<string, ProductEntity> d =
    new Dictionary<string, ProductEntity>()
    {
    {“prd0″, new ProductEntity(){ProductId=”prd0”,
        ProductName=”Windows”,
        ProductCost=20000}},
    {“prd1″, new ProductEntity(){ProductId=”prd1”,
        ProductName=”SharePoint”,
        ProductCost=30000}}
    };
public static ProductEntity ReadItem(string id)
{
    return new ProductEntity() { ProductId = d[id].ProductId,
        ProductName = d[id].ProductName,
        ProductCost = d[id].ProductCost};
}
public static IEnumerable<ProductEntity> ReadList()
{
    return d.Values;
}

以上で、外部リストの編集は完了です。
このまま配置して使用することもできますが、以降では、 アイテムの更新 (Update) 用のメソッドを実装して、セッションでもご紹介したように SharePoint 上で変更できるようにしてみましょう。

更新メソッドの作成

BdcModel1.bdcm のデザイナー上で、メソッド名を右クリックして [Add new Method] メニューを選択し、「Update」という名称のメソッドを追加します。以下の手順で、この作成されたメソッドのインスタンス (Instance) とパラメータ (Parameter) を設定します。

画面下部の [BDC Model Details] ウィンドウで、[Update] – [Instances] の下に「Update」という名称のインスタンスを追加します。また、この追加したインスタンスが更新用のメソッドであることを示すために、このインスタンスの [Type] プロパティを「Updater」に変更します。

つぎの手順でこの「Update」メソッドに入出力のパラメータを設定しますが、Updater のメソッドの場合、Return パラメータはなく、変更するアイテムの Identifier と、変更後のアイテム (ProductEntity オブジェクト) の双方が In パラメータとして渡されます。(Update メソッドの実装コードでは、この渡された ProductEntity オブジェクトを使用して、実際の更新処理を記述します。)

  • [Name] が「id」(名称は任意です)で、[Parameter Direction]が「In」のパラメータを追加します。
  • 上記で追加されたパラメータの TypeDescriptor をクリックすると、プロパティウィンドウに TypeDescriptor の編集画面が表示されるため、この TypeDescriptor の [Name] を「ProductId」(これも任意です)、[Type Name] を「System.String」、[Identifier] を「ProductIdentifier」、[Pre-Updater Field]を「True」に設定します。
  • さらに、[Name] が「productEntity」(これも任意です)で、[Parameter Direction]が「In」のパラメータを追加します。
  • 同様に、この追加されたパラメータの TypeDescriptor をクリックすると、プロパティウィンドウに TypeDescriptor の編集画面が表示されるため、TypeDescriptor の [Name] を「Entity1」(これも任意です)、[Type Name] (型の情報) を「BdcModelProject1.BdcModel1.ProductEntity, BdcModel1」に設定します。
  • さらに、前述で ProductCost を追加した際と同様の手順で、[BDC Explorer] を使用して、上記で作成した「Entity1」に ProductId、ProductName、ProductCost の各パラメータ用の TypeDescriptor を追加します。

    まず、[BCD Explorer] で、BdcModel1 – Product – Update – productEntity – Entity1 を右クリックして、[Add Type Descriptor] を選択して「ProductId」 の TypeDescriptor を追加します。ProductId では、[Name] を「ProductId」、[Type Name] を「System.String」、[Identifier] を「ProductIdentifier」、そして、[Updater Field] を「True」に設定します。

  • 同様に ProductName 用の TypeDescriptor を追加し、[Name] を「ProductName」、[Type Name] を「System.String」、さらに、[Updater Field] を「True」に設定します。
  • 同様に ProductCost 用の TypeDescriptor を追加し、[Name] を「ProductCost」、[Type Name] を「System.Int32」、[Updater Field] を「True」に設定します。

上記で、モデル上の「Update」メソッドの設定は完了です。
つぎに、デザイナー上で、作成した「Update」メソッドを右クリックして [View Code] メニューを選択すると、ProductService.cs に自動作成された Update メソッドのコードが表示されるので、ここに以下のコードを記述します。(引数には、上記で追加したパラメータである id と productEntity が設定されているのがわかります。)

public static void Update(string id, ProductEntity productEntity)
{
    d[id].ProductId = productEntity.ProductId;
    d[id].ProductName = productEntity.ProductName;
    d[id].ProductCost = productEntity.ProductCost;
}

以上ですべて完了です。
いろいろと大変なように思えるかもしれませんが、BDC の難解な XML を手で編集していたことを思えば、非常に楽な設定ですね。 

動作確認

ビルドして配置をおこない、動作を確認してみましょう。

まず、SharePoint を起動して、リストの作成をおこないます。この際、リストの種類として [Entity List] を選択します。

表示される画面で、[Name] 欄に適当なリスト名を入力し、[External Content Type] 欄として上記でインストールされた BCS のエンティティを選択します。

リストを作成すると、下図の通り表示され、このリストでは通常の SharePoint のリストのように変更もおこなうことが可能です。

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s