SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(CData)(AD)

EntityFramework対応で、よりC#やVB.NETのコードからアクセスしやすくなった「CData for Salesforce」

「CData ADO.NET Provider for Salesforce」の紹介

  • このエントリーをはてなブックマークに追加

 「CData ADO.NET Provider for Salesforce」(以下、CData)を使うとVB.NETやC#のコードからSalesforceが使いやすくなります。このときの接続方法には大きく分けて2つの方法が存在します。接続方法の一つは以前紹介したADO.NETインターフェースを使ってプログラミングする方法で、もう一つは今回紹介するEntityFrameworkを使った方法です。

  • このエントリーをはてなブックマークに追加

 EntityFrameworkを使うとSalesforceのテーブルがクラスとして使えるため、データアクセスが抽象化されてよりデータアクセスを意識せずにプログラムコードを記述できます。

Salesforceの準備

 自前のアプリからSalesforceに接続するためには、無料トライアルではなくDeveloper Editionを利用します。実運用する場合は、SalesforceのエディションとしてEnterprise EditionまたはUnlimited Editionが必要です。

 ログイン方法としては、ID、パスワード、セキュリティトークンの3つを指定してログインします。セキュリティトークンを未入手の場合はSalesforceにログインして[私の設定]からセキュリティトークンのリセットによりセキュリティトークンを入手しておいてください。

セキュリティトークンのリセット
セキュリティトークンのリセット
  1. [個人用]メニューを選択
  2. [私のセキュリティトークンのリセット]メニューを選択
  3. [セキュリティトークンのリセット]ボタンをクリック

 これでセキュリティトークンが登録してあるメールアドレスにメールで届きます。

Visual Studioからの接続

 コードから接続する前にSalesforceとの接続が可能かをサーバーエクスプローラーからデータ接続を行って確認しておくことをお勧めします。このような工程を経ることで、接続経路が悪いのか、プログラムが悪いのかの切り分けが容易になります。

接続の追加

 サーバーエクスプローラーで[データ接続]に対して[接続の追加]を行います。

接続の追加
接続の追加

 [接続の追加]ダイアログでは、Salesforceに登録したユーザID、パスワードそしてメールで送られてきたセキュリティトークンを[User]欄、[Password]欄、[Security Token]欄にそれぞれ設定します。

データ表示

データ表示
データ表示

 設定が完了すればサーバーエクスプローラーに[CData]ノードが追加されるので[Tables]ノードから試しに[Account]に対してデータ表示を行ってみましょう。

EntityFrameworkをコードで定義する

 それでは、Salesforceのキャンペーンページで表示される内容をCData経由で表示するサンプルを作成してみましょう。

 キャンペーンページの内容はCampaignテーブルに格納されています。サーバーエクスプローラーで確認してみましょう。

Campaignテーブル
Campaignテーブル

新規プロジェクトの作成

 [ファイル]-[新しいプロジェクト]メニューを選択して[Windowsデスクトップ]-[WPFアプリケーション]を選択してWPFアプリの新規プロジェクトを作成します。

EntityFrameworkライブラリの追加

 NuGetを使ってEntityFramework 6(執筆時点の最新は6.1.3)をプロジェクトに追加します。

NuGetで追加
NuGetで追加

参照設定

 CDataのインストールフォルダ配下のlib\4.0にあるSystem.Data.CData.Salesforce.Entities.EF6.dllを参照設定します。

参照設定
参照設定

接続文字列の設定

 App.configにSalesforceに接続するためのConnectionStringsを設定します。

リスト1 App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    :
  (略)
    :
  <connectionStrings>
    <add name="SalesforceContext" 
          connectionString="User=【1】;Password=【2】;Security Token=【3】;" 
          providerName="System.Data.CData.Salesforce" />
  </connectionStrings>
    :
  (略)
    :
</configuration>

 【1】【3】にはサーバーエクスプローラーで確認済のID、パスワード、セキュリティトークンを指定します。

Salesforceアクセス用クラス

 最初に用意するのはCampaignテーブルをクラス定義にしたものです。

リスト2 Campaignクラス
Public Class Campaign
    <DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)>
    Public Property Id As String
    Public Property Name As String
    Public Property Type As String
    Public Property Status As String
    Public Property StartDate As DateTime
    Public Property EndDate As DateTime
    Public Property ExpectedRevenue As Double
    Public Property BudgetedCost As Double
    Public Property ActualCost As Double
End Class

 テーブルの項目をすべて列挙する必要はありません。必要な項目だけを列挙します。1つだけ注意するのは、プライマリーキー(今回のケースならばId)を必ず含めるようにしてください。

 次にSalesforceとの接続用クラスを定義します。この中で先ほど作成したCampaignテーブル用のクラスを指定します。

リスト3 SalesforceContextクラス
Public Class SalesforceContext
    Inherits DbContext

    Public Property Campaign As DbSet(Of Campaign)

    Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
        System.Data.Entity.Database.SetInitializer(Of SalesforceContext)(Nothing)
        modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)()
    End Sub
End Class

コードからEFを利用する

 準備が完了したので、SalesforceContextを使ってデータを取得するModelクラスを作成します。

リスト4 SalesforceModelクラス
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Namespace Models
    Public Class SalesForceModel
        Implements INotifyPropertyChanged

        Public Property Items As New ObservableCollection(Of Campaign)

        Public Sub GetCampaign()
            Dim ents = New SalesforceContext()
            Dim campaignQuery = From item In ents.Campaign Order By item.Id Select item

            Me.Items = New ObservableCollection(Of Campaign)(campaignQuery)
            OnPropertyChanged("Items")
        End Sub

        Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
            Implements INotifyPropertyChanged.PropertyChanged
        Private Sub OnPropertyChanged(<CallerMemberName> _
                                      Optional propertyName As String = Nothing)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
        End Sub
    End Class
End Namespace

 SalesforceContextはLINQで操作できる形のオブジェクトになるので、取得後にLINQを使って並び替えを行っています。その後、ObservableCollection型のItemsプロパティに設定し画面からBindingにより参照できるようにしておきます。

Binding用ViewModel

 ModelとViewを連携するためのViewModelを作成します。

リスト5 MainViewModel
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Imports CZ1411Spread.Models
Imports System.Collections.ObjectModel
Imports CZ1411Spread.Common

Namespace ViewModels
    Public Class MainViewModel
        Implements INotifyPropertyChanged

        Private WithEvents Model As New SalesForceModel

        Public Property Items As ObservableCollection(Of Campaign)
            Get
                Return Me.Model.Items
            End Get
            Set(value As ObservableCollection(Of Campaign))
                Me.Model.Items = value
            End Set
        End Property

        Private _GetCommand As RelayCommand
        Public Property GetCommand() As RelayCommand
            Get
                If _GetCommand Is Nothing Then
                    _GetCommand = New RelayCommand(AddressOf Me.GetCampaign)
                End If
                Return _GetCommand
            End Get
            Set(value As RelayCommand)
                _GetCommand = value
            End Set
        End Property

        Public Sub GetCampaign()
            Dim userID = "hatsune@wankuma.com"
            Dim password = "hogehoge"
            Me.Model.GetCampaign(userID, password)
        End Sub

        Private Sub Model_PropertyChanged(sender As Object, …
            OnPropertyChanged(e.PropertyName)
        End Sub

        Public Event PropertyChanged(sender As Object, …

        Private Sub OnPropertyChanged(<CallerMemberName> Optional propertyName  …
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
        End Sub
    End Class
End Namespace

GridViewを使ったView

 ObservableCollectionをGridViewに表示するViewを定義します。

リスト6 MainWindow.xaml
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sg="http://schemas.grapecity.com/windows/spreadgrid/2012" 
    x:Class="Views.MainWindow"
    Title="CZ1412Salesforce" Height="300" Width="498">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <DataGrid HorizontalAlignment="Left" 
                  VerticalAlignment="Top"
                  ItemsSource="{Binding Items}"
                  CanUserSortColumns="True" />
        <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10">
            <Button Content="GET" Command="{Binding GetCommand}" />
        </StackPanel>
    </Grid>
</Window>

実行結果

 このサンプルを実行すると、データが表示されていない画面が表示されます。[GET]ボタンをクリックすると、ViewModelのGetCommandが実行されてデータの取得が行われます。

実行結果
実行結果

まとめ

 EntityFramworkを利用することでADO.NETインターフェースのConnectionやCommand、データセットなどを意識する必要がなくなります。共通クラスとしてデータアクセス部分を隠蔽することで意図しないSQLの発行を未然に防ぐことができますし障害時の切り分けや対応もしやすくなります。ある程度以上の規模になるとEntityFrameworkは必要な手法になるので、CDataとあわせて効率よい開発を実現してみてはいかがでしょうか。

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8733 2016/03/14 11:36

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング