Welcome to MSDN Blogs Sign in | Join | Help

I’m writing this post mainly as a reference for myself to remember key points regarding the Managed Addin Framework (MAF). MAF is pretty complex and a developer needs some sort of a reference guide in order to use it effectively. Thats what I’ll try and achieve with this post.

Disclaimer: I’ll be extracting quite a lot of info from msdn for this post so you might read stuff you’ve already been through before. Again, this post is only for my reference and its going to be a long one.

Before I begin let me note a few good references to the Addin Framework:

  1. Daniel Moth’s MAF – Part 1
  2. Daniel Moth’s MAF – Version Resilience – Part 2
  3. Detailed MSDN Coverage
  4. MAF at CodePlex
  5. Pipeline Builder
Addin pipeline:

Addin pipeline 

Add-in overview:

The contract is loaded into both the host and addin app domains.

To pass through the isolation boundary any type should be serializable or should be a contract. If not a contract or a serializable type then it should be converted to one by the adapter segment in the pipeline.

The views are usually abstract base classes or interfaces which are statically bound to the host or the addin.

 

Developing the pipeline:

The addin side adapter and host side adapter segment convert the flow of types between the respective views and the contract.

The contract derives from IContract interface.

The diagram below depicts the segments of the pipeline requiring attributes.

Add-in model with required attributes on types. 

 

Description of the pipeline segments:
Pipeline segment Description
Host The application assembly that creates an instance of an add-in.
Host view of addin Abstract base class or interface.
Represents host’s view of types and methods used to communicate with the addin.
Host side adapter An assembly with one or more classes that adapts methods to and from the contract.
[HostAdapter] attribute.
Contract Interface deriving from IContract.
[AddInContract]
attribute
Addin side adapter [AddInAdapter] attribute.
Each assembly in the addin side adapter directory that has this attribute is loaded into the addin’s app domain.
Addin view Abstract base class or interface.
[AddInBase] attribute.
Each assembly in the addin views directory that has this attribute is loaded into the addin’s app domain.
Add In A type that performs service for the host.
[AddIn]

 

Pipeline Activation Path:

Add-in model with activation path.

Moving from right to left in the diagram:

1. The addin inherits the addin view.

2. The addin view is passed into the constructor of the addin side adapter.

3. The addin side adapter inherits the contract.

4. The contract is passed into the constructor of the host side adapter.

5. The host side adapter inherits the host view.

 

 

 

 

 

 

Steps involved in activation:

  1. The host application activates the add-in with the Activate method.

  2. The add-in, add-in view, add-in-side adapter, and the contract assemblies are loaded into the add-in's application domain.

  3. An instance of the add-in-side adapter is created using the add-in view (with the class identified by the AddInBaseAttribute attribute) as its constructor. The add-in-side adapter inherits from the contract.

  4. The add-in-side adapter, which is typed as the contract, is passed across the (optional) isolation boundary to the host-side adapter's constructor.

  5. The host view of the add-in, host-side adapter, and the contract assemblies are loaded into the host's application domain.

  6. An instance of the host-side adapter is created using the contract as its constructor. The host-side adapter inherits from the host view of the add-in.

  7. The host has the add-in, which is typed as the host view of the add-in, and can continue calling its methods.

Attributes required:

Host view of addin is the type passed to AddInStore.FindAddIns method meaning this type need not be discovered, hence no attribute required.

 

Pipeline Directory Structure:

Required directories for add-in development.

Important:

The host application and the host view of the add-in pipeline segment are typically deployed in the same directory, which can be at any location. The host application requires a reference to the host view of the add-in segment that represents the add-in to activate.

You are not required to have add-ins in the pipeline directory structure. If they are not in the pipeline directory structure, you must call the AddInStore.UpdateAddIns method or the RebuildAddIns method that takes the path to the containing directory of the add-ins as its parameter.

Change the Output path for the pipeline segments to their respective directories in the pipeline directory structure.

 

 

 

 

 

 

Pipeline deployment:

Pipeline details

Pipeline Segment References in Visual Studio:

When adding references from one segment to another make a reference to the segment’s project instead of the assembly.

To add a project reference:

  1. In Solution Explorer, right-click the References folder and choose Add Reference.

  2. On the Projects tab, choose the desired project and click OK.

  3. Under the References folder, click the project reference you just added.

  4. In the reference Properties, set Copy Local to False.

image

The host view of the add-in has no reference requirements but it is required for the host application.

This pretty much covers all the background required to work with the MAF. Of course a lot of important stuff hasn’t been covered here like the Lifetime management and details of contracts and views and adapters. But since this is only a quick reference I’ll leave it at this.

In the next post I’ll walthrough creating an addin and note down all the points to note while doing the same.

Until then…

Sidharth

In my previous post I gave a small heads up regarding Microsoft’s Sync Framework and one of the issues which I faced while using SQLCE as a client. To get the latest version of Sync Framework which at this point of time is the v2.0 CTP1 visit this link.

If you’ve read up on the Sync Framework then you should know that it can target a variety of stores. One of the server side stores that can be used is SQL Server 2008. SQL Server 2008 provides change tracking features that enable you to easily sync your data without losing changes.

However to use the powerful (read: troublesome) change tracking features you’d require a bit of ADO.NET code to perform some of the following tasks:

  1. Set change tracking to ON in the database, set the CHANGE_RETENTION (number of days changes are held) and whether to auto cleanup the changes.
  2. Enable change tracking for each table that will be participating in synchronization.
  3. Select any incremental inserts, updates or deletes that are happening on the server.
  4. Apply any incremental inserts, updates and deletes that are propagated from client to server.
  5. Get conflicting updates and deletes when changes are made to both client and server.
  6. Stored procedures to get a database-wide timestamp/version indicating when the last change was committed. (CHANGE_TRACKING_CURRENT_VERSION).

This bunch of ADO.NET code can be put into stored procedures and executed on the ‘08 Server. There is one small problem though: Points 3,4 and 5 above have to be repeated for each of the tables participating in synchronization. Well, not quite every point listed above for every table but almost... Let me explain below:

Upload Only Scenario

For a table on the server to work successfully with the upload only scenario requires that it has to have the following stored procedures:

  • SP to select incremental inserts – basically used to retrieve the schema of the table and send it to the client.
  • SP to apply inserts on the server.
  • SP to apply updates on the server.
  • SP to apply deletes on the server.

Download Only Scenario

In the download scenario a table has to be able to send back incremental inserts, updates and deletes that happened on the server back to the client. This means:

  • SP to select incremental inserts.
  • SP to select incremental updates.
  • SP to select incremental deletes.

Bidirectional Scenario

In the bidirectional scenario a table has to fulfill both scenarios above as well as be able to detect conflicts when rows are simultaneously updated or deleted on server and client.

  • SP to select incremental inserts.
  • SP to select incremental updates.
  • SP to select incremental deletes.
  • SP to apply inserts on the server.
  • SP to apply updates on the server.
  • SP to apply deletes on the server.
  • SP to get update conflict from the server.
  • SP to get delete conflict from the server.

In the case of your application having a handful of tables (hardly likely), you can manually go ahead and write these stored procedures. However you’d soon realize the repetitiveness in such a mundane task. Enter T4.

T4 is an acronym standing for text templating transformation toolkit. It’s basically a code generator hidden inside Visual Studio that you can use to wreak havoc :). The basic concept is that you create a file like  [AnyName].tt (notice the extension tt) and then run the transformation and it turns into [AnyName].cs or whatever extension you want it to have. You can interweave code and logic inside the .tt file and the result will be code generated in your output file. It’s a slightly tricky concept to get your head around at the first go, but persevere and you’ll find you can do amazing things with T4.

For a (yawn) intro to T4 visit the msdn site but to actually get productive with T4 and to see some sample code in action visit this post on Oleg Sych’s blog. Also go through the various articles on his blog, he’s done some pretty cool stuff with T4.

Although Visual Studio provides support for T4 they don’t make it really obvious, there’s no file-> new item template or Intellisense that will help you code on T4. You can download either Clarius T4 editor (look for the free edition) or Tangible Modelling Tools plus T4 editor.

Clarius does not have intellisense when you write code inside code blocks, this is present inside the Tangible Modelling tools download. If you’re ok with getting a UML modelling tool along with the T4 editor go for Tangible. (Note: Only some of the .NET class libraries are supported in the free edition of Tangible).

Coming back to this post, I’ve written a T4 template that contains the templates for all the stored procedures mentioned above. To use it perform the following steps:

  1. Download the attached ConsolidatedSyncScript.zip file.
  2. Extract the ConsolidatedSyncScript.tt file and add it to a new project in Visual Studio.
  3. Double click the ConsolidatedSyncScript.tt file and click Ctrl + S. If you get any warning saying that the generator could harm your computer (yeah right) just click Ok (you’re cool with it right).
  4. Once you’ve done Ctrl + S you should see the ConsolidatedSyncScript.sql file as a sub file to the .tt file.
  5. Enjoy!!!

The script that I’ve provided here basically creates the structure of the stored procs for a sample database and sample tables which have to participate in synchroniztion. To actually work with your own database you’ll have to modify some code in the .tt file to generate the stored procedures for all your tables. If you’re upto it go ahead, if not, mail me sometime and I can provide a utility that you point to a database and it will generate all the stored procs for you.

I love T4!!!

 

    {Article updated towards the end: There is no issue with change tracking here}

    Microsoft Sync Framework provides synchronization capabilities between diverse data stores with the ability to implement custom sync providers targeting a multitude of stores.

    While working on the sync framework we have the option of using SQL Express or SQLCE as the client side database sync provider. In the solution currently being implemented in our application we used SQLCE 3.5 SP 1 as the client side database store.

    Sometime back one of my team members informed us that there was a bug with SQLCE related to the entity framework. There was a hot fix to resolve this issue so we all chose to download and install the hot fix.

    Its been a few months since then and while performing a few tests on the sync solution implemented by us I noticed that the client side change tracking was not getting updated as inserts and updates were manually being performed on the SQLCE db.

    On closer inspection I figured out that all upload related sync tests were failing whereas downloads were happening fine.

    Here are the steps I performed some of which passed and some failed: (those who have worked with the sync framework should be able to understand these)

    1. Create an sdf on the client.
    2. Create a table on the client sdf and populate with data.
    3. Set TableCreationOption to UploadExistingOrCreateNewTable
    4. Run a sync - verify if data has appeared on the server – YES - This happened successfully.
    5. Verify that the client table has been modified for changetracking – YES – values shown are zeros in both change tracking columns.
    6. Insert a row into client table - the change tracking columns show NULL for the inserted row.
    7. Update rows in the client table. - verify if the change tracking values change – NO- values remain as zeros for the updated row.
    8. Run a sync - verify if data is uploaded to server – NO – data is not uploaded to the server.
    9. Drop table on the client and delete all rows from the server table. (My attempt to clean up the client & server and start afresh).
    10. Set TableCreationOption to DropExistingOrCreateNewTable
    11. Run a sync - verify that schema has been created on the client – NO – Error during sync – details below (could not proceed with remaining steps)
    12. Insert data into client - check the change tracking values.
    13. Run sync - verify upload of inserted data.
    14. Update data in the client - verify the change tracking values.
    15. Run sync - verify upload of updated data.

    The error faced during step 11:

    Invalid column ID. [ __sysChangeTxBsn ]

    Source :

    SQL Server Compact ADO.NET Data Provider

    StackTrace :

       at System.Data.SqlServerCe.SqlCeChangeTracking.ProcessResults(Int32 hr)

       at System.Data.SqlServerCe.SqlCeChangeTracking.DisableTracking(String tableName)

       at Microsoft.Synchronization.Data.SqlServerCe.SqlCeClientSyncProvider.DisableOcsTracking(String tableName)

       at Microsoft.Synchronization.Data.SqlServerCe.SqlCeClientSyncProvider.EnableOcsTracking(String tableName, SETRACKINGTYPE seTrackingType)

       at Microsoft.Synchronization.Data.SqlServerCe.SqlCeClientSyncProvider.CreateOcsTable(String fmtTableName, Boolean createTable, SyncTable syncTable, SyncSchema syncSchema, SqlCeCommand cmdUtil)

       at Microsoft.Synchronization.Data.SqlServerCe.SqlCeClientSyncProvider.CreateSchema(SyncTable syncTable, SyncSchema syncSchema)

       at Microsoft.Synchronization.SyncAgent.InitClientSchema()

       at Microsoft.Synchronization.SyncAgent.DataSynchronize()

       at Microsoft.Synchronization.SyncAgent.Synchronize()

    Since there hadn’t been many code changes since the last time the tests had worked I guessed that SQLCE was playing its part in these errors. With some help from the sync framework team I figured that I was using a version of SQLCE that was higher than that being used by the sync framework team (also the one bundled as SQLCE 3.5 SP 1).

    I then reverted my SQLCE version to 3.5.5692.0 and found that the issue did not exist any longer.

    If you face any issues related to change tracking on the SQLCE database – the __sysChangeTxBsn or __sysInsertTxBsn columns don’t get modified as you update or insert values into the database, then make sure your version of SQLCE isn’t 3.5.5692.1.

    Issue solved…Sync framework upload scenario working successfully.

    Cheers!!!

    Sidharth

     

    [Update: Sidharth]

    This issue occurs only if you have an existing connection to the SQLCE DB open before the table in concern is configured for change tracking. It looks like the open connection does not recognise that change tracking has been enabled and treats the table as a normal table.

    The result of this is that even if the table has been configured for change tracking, if you use the same connection to update the table, the __sysChangeTxBsn or __sysInsertTxBsn do not get modified.

    This issue does not occur if you open a connection to the sdf after running sync once (basically get the table enabled for change tracking before you open a connection to the DB and start updating records).

    No issues with SQLCE.

    Great article by Andrew Hunter on the dangers of the large object heap.

    You can read it here: http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/ 

    Sid

    This is my first ever post so I'm gonna keep it short. Let me just say that it wasn't a breeze to get this blog set up, somehow didn't feel intuitive to me as it took a bit of fumbling and a bit of waiting :)

    Things are looking good now, the blog's all setup so I've just gotta post...

    Happy blogging!!!

    Sid

     
    Page view tracker