outlook sql · web viewthe sample was part an agile samples project from the sql server...

20
Outlook SQL Synchronization Sample Summary The Outlook SQL Sync sample uses the Microsoft Synchronization Framework 2.1 to demonstrate how to synchronize Outlook contacts stored on a LocalDB cache to a SQL Server instance. MVVM with a client workflow is used within an Outlook 2010 Add-in to show how to use a modern architectural pattern. The sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express LocalDB and SQL Server, Windows Workflow, WPF Topics Microsoft Synchronization Framework 2.1, SQL Express LocalDB and SQL Server, Client Windows Workflow, MVVM Prerequisites Visual Studio 2010 .NET Framework 4.0 SQL Server 2012 with LocalDB Microsoft Synchronization Framework 2.1 About the Sample Recently, the SQL Server User Education team started investigating how to apply agile development principles and practices to deliver customer samples. The underlying goal of agile samples development is

Upload: trinhlien

Post on 15-Mar-2018

217 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Outlook SQL Synchronization Sample

SummaryThe Outlook SQL Sync sample uses the Microsoft Synchronization Framework 2.1 to demonstrate how to synchronize Outlook contacts stored on a LocalDB cache to a SQL Server instance. MVVM with a client workflow is used within an Outlook 2010 Add-in to show how to use a modern architectural pattern. The sample was part an agile samples project from the SQL Server Customer Experience team.

TechnologiesMicrosoft Synchronization Framework 2.1, SQL Express LocalDB and SQL Server, Windows Workflow, WPF

TopicsMicrosoft Synchronization Framework 2.1, SQL Express LocalDB and SQL Server, Client Windows Workflow, MVVM

PrerequisitesVisual Studio 2010

.NET Framework 4.0

SQL Server 2012 with LocalDB

Microsoft Synchronization Framework 2.1

About the Sample

Recently, the SQL Server User Education team started investigating how to apply agile development principles and practices to deliver customer samples. The underlying goal of agile samples development is to get your feedback while we develop a sample. The idea is to break down a sample into user stories and short iterations. Then, our team will publish iterations with the goal of acquiring frequent customer feedback about the sample. Frequent customer feedback allows us to focus our sample’s development efforts on your needs.

As an early pilot for the idea, we created user stories and four iterations for an Outlook SQL Sync sample. This idea came from a customer request on MSDN samples for an Outlook Contact custom sync provider.

Page 2: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

My first step was to state the sample user stories then define the iterations. After chatting with an agile development expert in my group, I learned that effective user stories focus on the benefit of a feature to a role or persona. Simply put, in his own words, “As a (persona), I want to (feature), so that (benefit).” With this approach, the user story aligns more closely with the perspective of the customer.

Outlook SQL Sync User Stories

Initial Revised1. As an Outlook user, I am occasionally

disconnected from the network / internet. Therefore, I need my contacts available while offline.

1. As an Outlook Addin developer, I want to synchronize contact fields to a LocalDB SQL database so that data is stored in an offline data cache.

2. As an Outlook user, I want to synchronize contact fields to a SQL database.

2. As an Outlook Addin developer, I want to synchronize offline contact fields to a SQL Server database so that Outlook contacts are in sync with the AdventureWorks LOB database.

3. As a user, I want my contacts automatically synchronized with a SQL Server or SQL Azure contact table.

3. As an Outlook Addin developer, I want to provide an Outlook interface so that a user can easily synchronize contacts.

4. As a user, I want to be able to easily configure the sample application.

4. As a Technical Writer, I want to provide concise setup and configuration so that a user can quickly setup the sample.

5. As an administrator, I need to allow a list of specific users to read/write to a specific SQL table during a synchronization session.

5. As an Administrator, I want to allow a list of specific users to read/write to a specific SQL table during a synchronization session so that organizational security policies are enforced.

Note: This user story was removed from the sample.

6. As an Outlook user, I want to see the progress of an Outlook / contacts table synchronization.

6. As an Outlook Addin developer, I want to show progress of an Outlook / contacts table synchronization so that users can be notified of the synchronization progress.

7. As an Outlook user, I want to view a history of synchronization values.

7. As an Outlook Addin developer, I want to expose a historical view of synchronization values so that a user can diagnose synchronization activity.

Note: This user story was removed from the sample.

8. As a user, all of my existing contacts must be 8. As an Outlook Addin developer, I want to

Page 3: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

preserved while and after running the sample. preserve existing contacts while and after running the sample so that user contacts are not altered or removed.

A step diagram illustrates the progression of this sample.

How to setup the sample1. Install SyncSDK-v2.1-x86-ENU.msi.

Note The sample uses the x86 version of Microsoft Synchronization Framework 2.1 due to a COM class factory exception using the 64-bit version. For more information, see http://social.microsoft.com/Forums/en-US/syncdevdiscussions/thread/34a04f62-014a-48a0-9397-256b6ad1387b.

2. Attach AdventureWorks2012_SyncSample to a SQL Server 2012 instance. See How to install AdventureWorksLT2012_SyncSample database.

3. Attach AdventureWorks_localdb_2012 to (localdb)\v11.0. See How to install AdventureWorksLT2012_localdb_SyncSample database on SQL Express LocalDB.

4. Open the OutlookSyncSQL.sln solution from iteration 3 or 4.5. Provision SQL Server Synchronization. See How to configure the sample SQL Server

Synchronization.6. Start the Solution. This registers the Outlook Addin and start Outlook.

Page 4: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Optional – Enable Outlook Sync by creating a Sync workflow (Iteration 4)1. Copy {path}\OutlookSyncSQL\SyncWorkflow\Workflow\BlankWorkflow\

SyncWorkflow.xaml to {path}\OutlookSyncSQL\SyncWorkflow\Workflow\.2. From Outlook, click the Contacts folder.3. Click the SQL Server Samples ribbon tab.

4. Click the Designer button which loads the sample client workflow designer.

5. Drag a NotifyStartedActivity from the activity toolbox onto the empty Sequence activity.

6. Drag a NotifySyncUpdatedActivity under the NotifyStartedActivity.7. Select the NotifySyncUpdatedActivity and set the following properties in the Activity

PropertyGrid:

ClientDataSource

Page 5: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

“Data Source=(localdb)\v11.0;Initial Catalog=AdventureWorksLT2012_localdb_SyncSample;Integrated Security=True”

ScopeName

Select ContactsScope from the ComboBox dropdown.

ServerDataSource

“Data Source=.;Initial Catalog=AdventureWorksLT2012_SyncSample;Integrated Security=True;Connect Timeout=1”

8. Drag a NotifyCompletedActivity below the NotifySyncUpdatedActivity.9. Close the designer window. For the sample, the workflow auto-saves.

Final Client SyncWorkflow

How to install AdventureWorksLT2012_SyncSample databaseThe OutlookSyncSQL sample uses a slightly modified version of AdventureWorksLT2012. The AdventureWorksLT2012_SyncSample database can be installed using the CREATE DATABASE statement or by attaching the database.

To install AdventureWorksLT2012_SyncSample database

From SQL Server Management Studio, execute the following T-SQL code:

CREATE DATABASE AdventureWorksLT2012_SyncSample ON (FILENAME = '{drive}:\{ OutlookSyncSQL Path}\AdventureWorksLT2012_SyncSample_Data.mdf’) FOR ATTACH_REBUILD_LOG;

Page 6: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

As an alternative, you can attach the database with SQL Server Management Studio user interface. For more detailed information, see Attach a Database (SQL Server Management Studio).

How to install AdventureWorksLT2012_localdb_SyncSample database on SQL Express LocalDBThe AdventureWorksLT2012_localdb_SyncSample database can be installed using the CREATE DATABASE statement or by attaching the database.

To install AdventureWorksLT2012_localdb_SyncSample database

From SQL Server Management Studio, execute the following T-SQL code:

CREATE DATABASE AdventureWorksLT2012_localdb_SyncSample ON (FILENAME = '{drive}:\{OutlookSyncSQL Path}\AdventureWorksLT2012_localdb_SyncSample.mdf’) FOR ATTACH_REBUILD_LOG;

As an alternative, you can attach the database with SQL Server Management Studio user interface. For more detailed information, see Attach a Database (SQL Server Management Studio).

How to configure the sample SQL Server SynchronizationTo configure the sample SQL Server Synchronization, run the following unit tests contained in the OutlookSyncTestProject project.

SyncFrameworkUnitTest.ProvisionServerScope() test method to provision the server scope. SyncFrameworkUnitTest.ProvisionClientScope() test method to provision the client LocalDB

scope.

How to run the sampleOpen OutlookSyncSQL.sln in Visual Studio 2010 and run the sample. Once the solution opens Outlook, you will see a SQL Server Samples ribbon tab after you click the Outlook Contacts folder.

Steps

1. From the SQL Server Samples ribbon, click the SQL Server Sync Task Pane button.2. Make a few changes to the sample AdventureWorks contacts.3. On the Sync Sample task pane, click the Sync button.

Note For iteration 4, if a “Cannot create unknown type '{clr-namespace: Microsoft.Samples.SqlServer.SyncClientWorkflow}NotifyStarted'” exception is thrown, then modify the xmlns:local attribute within SyncWorkflow.xaml by appending ;assembly=Microsoft.Samples.SqlServer.SyncClientWorkflow.

Fully qualified xmlns:local attribute

Page 7: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

xmlns:local="clr-namespace:Microsoft.Samples.SqlServer.SyncClientWorkflow;assembly=Microsoft.Samples.SqlServer.SyncClientWorkflow

Page 8: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Agile SamplesThe OutlookSyncSQL sample was developed to learn more about how the SQL Server Customer Experience team could use agile principles to deliver more frequent iterations. Agile sample development principles apply to how work is planned as well as loosely-coupled development principles. User stories were used to plan short iterations which allowed development focused on delivering a functional part of the sample scenario. See About the Sample for user stories addressed in this sample. Development principles including Test-driven development, MVVM, and client workflows were used to illustrate how to create a loosely-coupled WPF user control hosted in an Outlook task pane. A Test-driven development approach tests parts of the sample as discrete methods with the Visual Studio Unit Testing Framework. MVVM design principles of a NotifySyncUpdatedActivity containing a synchronization model extension, and a synchronization view model bound to a WPF user control are illustrated.

Test-driven Development

The OutlookSyncSQL sample utilized Test-driven development as an efficient means to write discrete test methods that use the Visual Studio .NET 2010 Unit Testing Framework. One advantage of discrete unit test methods is that you focus on verifying that specific functionality works and does what it should do. Each verified test method is then integrated into the functional sample. For example, the Synchronize() TestMethod verifies synchronization occurred between the LocalDB cache and the SQL Server instance. The verified code was used to create the SqlContactSync.Synchronize() method for iteration 3 and the NotifySyncUpdatedActivity for iteration 4.

Page 9: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Example TextMethod

[TestMethod]public void Synchronize(){ SyncOperationStatistics syncStats = null;

// Create a connection to the LocalDB database using (SqlConnection clientConnection = new SqlConnection(@Properties.Settings.Default.LocalDBConnectionString)) { // Create a connection to the Server database using (SqlConnection serverConnection = new SqlConnection(@Properties.Settings.Default.ServerConnectionString)) { // Create the sync orhcestrator SyncOrchestrator syncOrchestrator = new SyncOrchestrator();

// Set local provider of orchestrator to a LocalDB (SQL) provider associated with the syncOrchestrator.LocalProvider = new SqlSyncProvider(scopeName, clientConnection);

// Set the remote provider of orchestrator to a server sync provider associated with syncOrchestrator.RemoteProvider = new SqlSyncProvider(scopeName, serverConnection);

// Set the direction of sync session to Upload and Download syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;

// execute the synchronization process syncStats = syncOrchestrator.Synchronize();

Assert.IsTrue(syncStats.SyncEndTime > syncStats.SyncStartTime); } } }

Page 10: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Iteration 3 – Sample SqlContactSync Class using unit test code

class SqlContactSync{ private string scopeName = "ContactsScope";

public SyncOperationStatistics Synchronize() { SyncOperationStatistics syncStats = null;

// Create a connection to the LocalDB database using (SqlConnection clientConnection = new SqlConnection(@Properties.Settings.Default.LocalDBConnectionString)) { // Create a connection to the Server database using (SqlConnection serverConnection = new SqlConnection(@Properties.Settings.Default.ServerConnectionString)) { // Create the sync orhcestrator SyncOrchestrator syncOrchestrator = new SyncOrchestrator();

// Set local provider of orchestrator to a LocalDB (SQL) provider associated with the syncOrchestrator.LocalProvider = new SqlSyncProvider(scopeName, clientConnection);

// Set the remote provider of orchestrator to a server sync provider associated with syncOrchestrator.RemoteProvider = new SqlSyncProvider(scopeName, serverConnection);

// Set the direction of sync session to Upload and Download syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;

// execute the synchronization process syncStats = syncOrchestrator.Synchronize(); } }

// Execute the synchronization process return syncStats; }}

Page 11: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Iteration 4 - NotifySyncUpdatedActivity using unit test code

[Designer(typeof(Microsoft.Samples.SqlServer.SyncClientWorkflow.NotifySyncUpdatedActivityDesigner))]public sealed class NotifySyncUpdatedActivity : CodeActivity{ //InArgument<string> not used since argument is set using a PropertyValueEditor public string ScopeName { get; set; } public InArgument<String> ClientDataSource { get; set; } public InArgument<String> ServerDataSource { get; set; } public OutArgument<SyncOperationStatistics> SyncOperationStatistics { get; set; }

// Since designer and activity are in same assembly register in static constructor static NotifySyncUpdatedActivity() { AttributeTableBuilder builder = new AttributeTableBuilder(); builder.AddCustomAttributes(typeof(NotifySyncUpdatedActivity), "ScopeName", new EditorAttribute(typeof(ScopeNameInlineEditor), typeof(PropertyValueEditor)));

MetadataStore.AddAttributeTable(builder.CreateTable()); }

public NotifySyncUpdatedActivity(){ }

#region Execute Method protected override void Execute(CodeActivityContext context) { string clientDataSource = this.ClientDataSource.Get(context); string serverDataSource = this.ServerDataSource.Get(context);

var model = context.GetExtension<SyncModel>();

SyncOperationStatistics syncStats = null;

// Create a connection to the LocalDB database using (SqlConnection clientConnection = new SqlConnection(@clientDataSource)) { // Create a connection to the Server database using (SqlConnection serverConnection = new SqlConnection(@serverDataSource)) { // Create the sync orhcestrator SyncOrchestrator syncOrchestrator = new SyncOrchestrator();

// Set local provider of orchestrator to a LocalDB (SQL) provider associated with the syncOrchestrator.LocalProvider = new SqlSyncProvider(this.ScopeName, clientConnection);

Page 12: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

// Set the remote provider of orchestrator to a server sync provider associated with syncOrchestrator.RemoteProvider = new SqlSyncProvider(this.ScopeName, serverConnection);

// Set the direction of sync session to Upload and Download syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;

// Execute the synchronization process syncStats = syncOrchestrator.Synchronize();

SyncOperationStatistics.Set(context, syncStats); } }

//Update the model model.DownloadChangesTotal = syncStats.DownloadChangesTotal; model.UploadChangesTotal = syncStats.UploadChangesTotal; if (model.Updated != null) { model.Updated(); } }

#endregion}

MVVM and Client WorkflowThe final sample iteration used a MVVM design pattern with a synchronization activity with model extension, and a synchronization view model bound to a WPF user control hosted on an Outlook task pane. MVVM facilitates a clear separation between the WPF user interface, the view, and the business logic, the model. The view model handles display objects containing observable properties and commands that the WPF view can bind to. The model and view model can be independently developed and tested.

The NotifySyncUpdatedActivity activity with model extension encapsulates synchronization of the AdventureWorks LocalDB database and SQL Server database. Windows Workflows can run in any managed process. This sample shows how a client workflow activity can be hosted within an Office Addin. The sample runs the workflow within Outlook; however, the NotifySyncUpdatedActivity could participate in an Excel Addin. The SyncModel model, which derives from ClientModelBase implementing ISyncModel, is passed to NotifySyncUpdatedActivity as a workflow extension. This allows the activity to notify the model about events in the workflow. The sample SyncModel exposes a subset of Synchronization Framework properties.

SyncModel modelThe job of the model in MVVM is to represent the data and the processes that are exposed to the UI. The model knows nothing about the UI that it consumes it. The separation allows the developer to

Page 13: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

focus on creating an object that encapsulates the necessary business logic and data access code in a highly testable fashion.

SyncModel

ClientModelBaseClass

Properties

DownloadChangesTotalUploadChangesTotal

Methods

OnAbortedStartSyncModel

ISyncModel

Testing the ModelWhen testing the model, take into account the WorkflowApplication runs run the workflow on a different thread. Synchronization objects can be used to cause the test thread to wait.

private const int TestTimeout = 10000;

[TestMethod]public void ModelUpdated(){ var updated = new AutoResetEvent(false);

SyncModel model = new SyncModel();

model.Updated = () => updated.Set();

model.Start(null);

//Wait for syncOrchestrator.Synchronize(); updated.WaitOne(TestTimeout);

Assert.IsTrue(model.UploadChangesTotal > 0);}

Notify ActivitiesThe sample uses notify activities to support client notifications from a workflow. The activities obtain the model from the extensions collection. If an Action<T> notification delegate is provided, the activity invoke the delegate method.

Sample notify activities

Page 14: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

NotifyStartedActivity – Notify the SyncModel that the workflow started. NotifySyncUpdatedActivity – Execute synchronization between an AdventuerWorks LocalDB

instance and a SQL Server instance. Populate SyncModel properties and notify that the workflow updated the model.

NotifyCompletedActivity - Notify the SyncModel that the workflow completed.

SyncViewModel view modelThe purpose of the view model is to provide the interface that a particular View needs. A view creates an object surface that allows WPF controls to data bind to both properties and commands.

Page 15: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express
Page 16: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Testing the ViewModelThe ViewModel TestMethod tests the UploadChangesTotal property without any knowledge of the UI.

- C# code snippet -

Testing the ViewModel[TestMethod]public void ViewModelPropertyTest(){ var target = new SyncViewModel(); var started = new AutoResetEvent(false); target.Started += () => started.Set();

var propertyChangedNotified = false; target.PropertyChanged += (o, e) => { if (e.PropertyName == "UploadChangesTotal") { propertyChangedNotified = true; } };

target.Start();

started.WaitOne(TestTimeout);

// Verify the UploadChangesTotal was set Assert.IsTrue(target.UploadChangesTotal > 0);

// Verify that the PropertyChanged event was fired Assert.IsTrue(propertyChangedNotified);}

- end -

Binding to ViewModel Properties

<TextBlock FontSize="12" Text="Upload Changes:" Margin="3,6,82,163" Grid.Row="1" Grid.ColumnSpan="2" /> <TextBlock FontSize="12" Text="{Binding Path=UploadChangesTotal, Mode=OneWay}" Margin="38,6,2,163" Grid.Row="1" Grid.Column="1" /> <TextBlock FontSize="12" Text="{Binding Path=Status, Mode=OneWay}" Margin="3,99,456,70" Grid.Row="1" Grid.ColumnSpan="3" /> <TextBlock FontSize="12" Grid.ColumnSpan="2" Margin="3,39,74,130" Text="Download Changes:" Grid.Row="1" /> <TextBlock FontSize="12" Text="{Binding Path=DownloadChangesTotal, Mode=OneWay}" Margin="38,39,2,130" Grid.Row="1" Grid.Column="1" />

Page 17: Outlook SQL · Web viewThe sample was part an agile samples project from the SQL Server Customer Experience team. Technologies Microsoft Synchronization Framework 2.1, SQL Express

Binding to Commands

<Button FontSize="12" Grid.Row="1" Command="{Binding Path=StartCommand}" Height="25" Margin="3,71,18,99">Sync</Button>

ConclusionThe OutlookSQLSync sample addressed a customer request for how to synchronize Outlook contacts to a SQL table. This sample uses a LocalDB cache along with Microsoft Synchronization SqlSyncProvider provider to illustrate one way to for data synchronization. Synchronization to the LocaDB cache is performed with a custom sync class since that is more appropriate in a single user environment. The sample uses the Microsoft Synchronization Framework to for data synchronization within a multi-user environment.