Belgian eID and .NET - Part 2: Modify the middleware and remove the confirmation dialog
In my previous post I talked about how you could build the eID middleware and create a sample application that uses the eID. When you start an application that uses the middleware you'll see the following confirmation dialog that asks the user for permission to access the card.

An end user wouldn't want this dialog to pop up all the time while working with eID cards. But since we have the sources we can modify the middleware and suppress the confirmation dialog. Let's get started!
Modify the sources
Open the Visual Studio solution 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\BeidEasyBuild_VS2008.sln' we downloaded in the previous article. The confirmation dialog shows the message: The following application 'xxx' is trying to read data on the eID card. This is a good starting point to find the code resulting in this confirmation dialog.
When you search for this text in the solution you'll find the text in the header file 'eid-mw-3.5.5\eid-mw\_src\eidmw\dialogs\language.h' where the string is saved in a constant named TheFollowingApplication1IsTrying. This constant is used in the file 'eid-mw-3.5.5\eid-mw\_src\eidmw\dialogs\langUtil.cpp' where it is part of the complete dialog text. This text is built in a switch statement under the DLG_MESSAGE_USER_WARNING case. Finally we can track this back to the APL_EIDCard::askWarningLevel method in 'eid-mw-3.5.5\eid-mw\_src\eidmw\applayer\APLCardBeid.cpp'. Adapt the method to always set the warning level to ACCEPTED and return immediately.
void APL_EIDCard::askWarningLevel()
{
APL_AccessWarningLevel lWarningLevel=getWarningLevel();
if(lWarningLevel==APL_ACCESSWARNINGLEVEL_REFUSED)
throw CMWEXCEPTION(EIDMW_ERR_NOT_ALLOW_BY_USER);
if(lWarningLevel==APL_ACCESSWARNINGLEVEL_BEING_ASKED)
throw CMWEXCEPTION(EIDMW_ERR_USER_MUST_ANSWER);
if(lWarningLevel==APL_ACCESSWARNINGLEVEL_TO_ASK)
{
// Set the warning level to accepted without displaying the dialog.
setWarningLevel(APL_ACCESSWARNINGLEVEL_ACCEPTED);
return;
}
}
That's it. Now it's time to rebuild correctly.
Rebuild
First you need to rebuild the applayer project. Just like in the previous article you need to copy the *.lib file to the other directory. So copy 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\Release\applayer.lib' to 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\' and rename the file to beid35applayer.lib. After the file has been renamed you need to build the libCS_Wrapper project by right clicking it and choosing Build.
The directory 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release' will contain the updated libraries. Now just copy these files to the output directory of your application and you'll be able to access the eID card without confirmation from the user.
Download the sample application (C#): SanLib.eID.Test.zip (932.19 kb)
Enjoy...
Belgian eID and .NET - Part 1: Getting Started
Lately I've been looking into federated authentication and now I want to go further and see how the Belgian eID fits in this story. But the amount of documentation (especially for .NET) seems blurry, incomplete and outdated to say the least. That's why I'm planning to write a few articles that will help you get on your way to use the eID in your .NET applications.
Before we get started I do need to mention the free eIDnative library (http://www.eidnative.be/) that could fit your needs. The problem I have with this library is that from time to time I experienced some nasty bugs like "An attempt was made to write to read only memory". And since the library hasn't been updated in almost a year it doesn't feel good to use this library in a production scenario.
This is the reason why I'm opting for the official way (using the official middleware and SDK). But this is where we bump into the first issue. What should you do to get the bits and bytes to create a working sample? If you have looked around you'll see a few outdated blog posts, some forum posts, a few projects on code.google.com and also pages on eid.belgium.be (http://eid.belgium.be/nl/Achtergrondinfo/De_eID_technisch/). Finally I decided to go for code.google.com since you'll get a complete overview of the existing solutions and seen the high activity this is where you'll be able to find newest versions of the middleware and the SDK.
Note: You can save yourself a lot of work by just downloading the library but if you follow this guide you'll be able to modify the middleware afterwards.
The bits and bytes
The online repository (http://code.google.com/p/eid-mw/source/browse/) allows you to browse branches and the current trunk (containing the unreleased version of the middleware). I'll be discussing how to start working with version 3.5.5 of the middleware.

Note that this is an SVN repository and we'll need to get the whole 3.5.5 branch locally. Before downloading the branch I created the following structure on my local disk:

What we'll need to do next is install TortoiseSVN (http://tortoisesvn.net/downloads.html) and check out the 3.5.5 branch. This is very easy to do since TortoiseSVN is a simple shell extension. You just need to right click the eid-mw-3.5.5 folder you just created and click the SVN Checkout... button.

TortoiseSVN will need you to enter the URL of the repository you're trying to check out. Since we're only interested in the 3.5.5 branch we'll be using the following URL: http://eid-mw.googlecode.com/svn/branches/3_5_5/

Press OK and the complete branch will be downloaded locally. Whenever a new version is made available you can use this technqiue to get the latest version. Follow the eID website (http://eid.belgium.be/nl/) or the Google Code page (http://eid-mw.googlecode.com/) to see if a new version is released.
Setting up the prerequisites
The rest of this article will explain how to get everything in the right place to build the required dll files. This will allow you to create a portable version of the middleware and also to make modifications where needed. In the next article I'll show how you can remove the annoying dialog that asks the end user for permission.
Here is a list of all prerequisites I needed on my machine to get everything working:
In the files you checked out there's also a file named beid_middleware_easybuild.pdf. This file explains which prerequisites you need, which scripts you need to adapt/run/... but that didn't seem to work well for me. This is why I decided to do it my way. Besides that, the branch contains a solution that can help you to easily build all files... but it still took me a few hours to get all the pre-requisites in the right place and get everything to work correctly.
Setting up OpenSSL
Browse to the eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\ directory and open the BeidEasyBuild_VS2008.sln solution file (if you're working with VS2010 you'll be prompted to convert the solution). You'll probably see a few projects marked as unavailable but that's not an issue for now. Right click the libCS_Wrapper project and choose build. After a few minutes you'll see a bunch of errors:

These errors are mostly due to the prerequisites not being in the right place. First we should fix the OpenSSL problem. Install Win32OpenSSL-0_9_8r.exe and select the option to copy DLLs to the OpenSSL binaries directory of the OpenSSL installation. After the installation completes you should copy the whole OpenSSL directory to eid-mw-3.5.5\eid-mw\_src\ThirdParty\ and rename it to openssl.0.9.8g
Browse to eid-mw-3.5.5\eid-mw\_src\ThirdParty\openssl.0.9.8g\ and take the following actions:
- Copy bin\libeay32.dll to lib\ and rename to libeay32_0_9_8g.dll
- Rename bin\ssleay32.dll to lib\ and rename to ssleay32_0_9_8g.dll
The directory should look like this:

If you try to build you'll see less errors, but we're not done yet.
Setting up Xerces
Extract xerces-c-3.1.1.zip and copy the directory 'xerces-c-3.1.1\src\xercesc' to 'eid-mw-3.5.5\eid-mw\_src\ThirdParty\xercesc'. The applayer project needs a few header files so it's time to configure the project for this. Right click the applayer project and click Properties. After that go to VC++ Directories and edit the Include Directories. Add both 'eid-mw-3.5.5\eid-mw\_src\ThirdParty\' and 'eid-mw-3.5.5\eid-mw\_src\ThirdParty\xercesc' to the Include Directories:

Now go to the 'eid-mw-3.5.5\eid-mw\_src\ThirdParty\xercesc\util' directory and rename Xerces_autoconf_config.msvc.hpp to Xerces_autoconf_config.hpp
After this is done go to 'xerces-c-3.1.1\projects\Win32\VC10\xerces-all' (from the zip file you extracted) and open the solution xerces-all.sln. Build the whole solution, we'll need some of the output for later. Don't forget to change the configuration from Debug to Release.
Setting up swigwin
Extract swigwin-1.3.35.zip and copy the contents of 'swigwin-1.3.35\swigwin-1.3.35\' to 'eid-mw-3.5.5\eid-mw\_src\ThirdParty\swigwin\'. We'll need this for later.
Building
Now the prerequisites have been set up it's time to start building. I'm not planning to debug the application so I decided to change the build configuration from Debug to Release. After that right click the libCS_Wrapper project and choose Build. You'll still see a few errors but that's not a problem. Go to the 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\Release' directory copy the file to 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release'. After copying the file rename it to beid35common.lib (in the '_Binaries32\Release' directory).
To avoid confusion this is how the files should be set up:
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\Release\common.lib
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\beid35common.lib
Once this is done right click DlgsWin32 project and choose Build and do the same for the cardlayer project. Repeat the previous step for the new files; this is how everything should look like:
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\Release\cardlayer.lib
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\beid35cardlayer.lib
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Builds\Release\DlgsWin32.lib
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\beid35DlgsWin32.lib
Go to the OpenSSL installation directory, copy the *.lib files from OpenSSL\lib\ to 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\'. After copying them you need to append '_0_9_8g' to the filename. As a result you should have the following files:
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\libeay32_0_9_8g.lib
- eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\ssleay32_0_9_8g.lib
Previously you needed to build the xerces solution. Now it's time to use the output of this project. Copy the file 'xerces-c-3.1.1\Build\Win32\VC10\Release\xerces-c_3.lib' to 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release\xerces-c_3.lib'.
Now build the applayer project and also for this project you'll need to copy the *.lib file and rename it. The contents of the Release directory should look like this:

The whole eID setup comes with a batch file 'set_path.bat' that allows you to customize directories containing the external dependencies but this batch file doesn't seem to work. Open the project file 'eid-mw-3.5.5\eid-mw\_src\eidmw\eidlibCS_Wrapper\beid35libCS_Wrapper_VS2008.vcxproj' with a text editor (like notepad) and replace each instance of %BEID_DIR_SWIG% with the full path to your swigwin directory. In my case this is X:\SVN\eid-mw-3.5.5\eid-mw\_src\ThirdParty\swigwin (make sure there is no trailing backslash at the end).
Go back to Visual Studio and you should get a notice that a project was modified outside Visual Studio. Press the Reload button to... reload the project. Finally build the projects libCS_35 and libCS_Wrapper by right clicking them and choosing Build. It could be that the common project still gives you 2 errors but that's nothing.
If all goes well you should see 2 new files in 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release':
- beid35libCS.dll
- beid35libCS_Wrapper.dll
That's it, you've done it! The eID middleware 3.5.5 has been built and can now be used in .NET applications. As I mentioned before the next article will show you how to make a small modification to the middleware.
A sample application
After building the projects you'll have a bunch of files in the 'eid-mw-3.5.5\eid-mw\_src\eidmw\_Binaries35\Release' directory. You'll need to use these files to create the sample application. I created a sample console application, referenced beid35libCS.dll and built the project.
Before you can actually start the project you'll need to copy the following files to the output directory:
- beid35applayer.dll
- beid35cardlayer.dll
- beid35common.dll
- beid35DlgsWin32.dll
- beid35libCS.dll
- beid35libCS_Wrapper.dll
- libeay32.dll (rename libeay32_0_9_8g.dll to libeay32.dll)
- ssleay32.dll (rename ssleay32_0_9_8g.dll to ssleay32.dll)
The code for the sample application is fairly simple:
try
{
BEID_ReaderSet readerSet = BEID_ReaderSet.instance();
BEID_ReaderContext reader = readerSet.getReader();
if (reader.isCardPresent())
{
BEID_EIDCard card = reader.getEIDCard();
BEID_EId doc = card.getID();
string firstname = doc.getFirstName();
Console.WriteLine("Firstname: " + firstname);
string lastname = doc.getSurname();
Console.WriteLine("Lastname: " + lastname);
string birthdate = doc.getDateOfBirth();
Console.WriteLine("Birthdate: " + birthdate);
}
BEID_ReaderSet.releaseSDK();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
When you execute the application you should see the following (make sure you have an eID card plugged into the reader):


Sample application: SanLib.eID.Test.zip (931.99 kb)
Enjoy...
TechDays Belgium 2011: Follow the speakers!
This year's TechDays is filled with big names and great sessions. When you're preparing for the event (choosing which session to go to etc...) you might want to discover some of the speakers. And during the event those speakers will probably be active on twitter. That's why I created a list of all speakers with their blogs, rss feeds and twitter accounts:
- Adam Gilmore (Solutions Architect / Microsoft Consulting Services UK): Blog RSS Twitter
- Bart De Smet (Software Development Engineer / Microsoft): Blog RSS
- Boris Jabes (Senior Program Manager, Visual C++ team / Microsoft Corp): Blog RSS Twitter
- Brian Keller (Sr. Technical Evangelist / Microsoft): Blog RSS
- Chris Eargle (Telerik Developer Evangelist, MVP / Telerik): Blog RSS Twitter
- Christian Weyer (Co-founder / Thinktecture): Blog RSS Twitter
- Clemens Vasters (Principal Technical Lead AppFabric / Microsoft Corporation): Blog RSS Twitter
- Corey Hynes (Technical Lead / Hynesite)
- Dan Holme (Intelliem): Blog RSS Twitter
- Dandy Weyn (Sr. Technical Product Manager - Core Database Product Management / Microsoft Corp): Twitter
- David Allen (Principal Consultant - OpsMgr MVP / Infront Consulting Group - Europe): Twitter
- Don Jones (Editor-in-Chief / Realtime Publishers): Twitter
- Gill Cleeren (.NET Architect / Ordina): Blog RSS Twitter
- Glenn Block (Senior Program Manager WCF / Microsoft Corp): Blog RSS Twitter
- Hadi Hariri (Technical Evangelist / JetBrains): Blog RSS Twitter
- Ilse Van Criekinge (Technology Advisor / Microsoft): Blog RSS Twitter
- Ingo Rammer (Co-founder / Thinktecture): Blog RSS Twitter
- Isabel Gomez Miragaya (ISV Developer Evangelist / Microsoft Spain)
- Jeff Prosise (Instructor, Consultant and Co-Founder / Wintellect): Blog RSS Twitter
- Jens K. Suessmeyer (Database Consultant / Microsoft Consulting Services, Germany): Blog RSS
- Jeremy Moskowitz (Chief Propeller-Head for Moskowitz, inc. and GPanswers.com / Moskowitz inc): Blog Twitter
- John Craddock (Principal Systems Consultant): Twitter
- Kevin Dockx (Technical Consultant / RealDolmen): Blog RSS Twitter
- Kim Oppalfens (Managing Consultant / OSCC): Blog RSS Twitter
- Kurt Claeys (Technology Solution Professional on Windows Azure / Microsoft EMEA)
- Kurt Roggen (Practice Leader / DevoTeam Belgium): Blog RSS Twitter
- Luc Van De Velde (Director Developer & Platform group / Microsoft): Blog RSS Twitter
- Maarten Balliauw (.NET Developer / RealDolmen): Blog RSS Twitter
- Marcus Murray (Security Team Manager at Truesec / Truesec): Blog RSS
- Mark Scurrell (Senior Program Management Lead / Microsoft Corp): Blog
- Mike Resseler (Senior Technical Consultant, SCDPM MVP / Infront Consulting Group – Europe): Blog RSS Twitter
- Phil Japikse (Patterns and Practices Evangelist / Telerik): Blog RSS Twitter
- Pieter Gheysens (Sparkles): Blog RSS Twitter
- Rob Miles (Lecturer / University of Hull): Site Twitter
- Ruben Spruijt (Technology Officer at PQR / PQR): Blog RSS Twitter
- Scott Hanselman (Principal Program Manager Lead / Microsoft Corporation): Blog RSS Twitter
- Scott Schnoll (Principal Technical Writer / Microsoft): Blog RSS Twitter
- Serge Luca (Sharepoint MVP consultant and trainer): Blog RSS
- Steffen Krause (Technology Advisor / Microsoft Germany): Blog RSS Twitter
- Symon Perriman (Program Manager - Clustering / Microsoft Corp): Blog Twitter
- Vittorio Bertocci (Senior Architect Evangelist / Microsoft): Blog RSS
- Wade Wegner (Sr Technical Evangelist / Microsoft Corporation): Blog RSS Twitter
Take your time to choose because you can't follow all sessions!
Enjoy...
HTTP Error 404.17: The requested content appears to be script and will not be served by the static file handler.
Today I bumped into the following error after deploying a WCF service:
HTTP Error 404.17 - Not Found
The requested content appears to be script and will not be served by the static file handler.
Most blog posts indicate that you should change the application pool identity to Classic .NET AppPool. In my case I had to change the application pool identity and (re-)execute the default WCF registration command to get the service working:
C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation>ServiceModelReg.exe -i
Enjoy!
DbProviderFactoryRepository: Managing DbProviderFactories in code
Today I started playing with SQL CE (Compact Edition) to see how it could be used in a Client Profile environment. These were my findings:
- Entity Framework does not work on the .NET 3.5 Client Profile
- In the .NET 4.0 Client Profile you do have access to System.Data.Entity
- Enterprise Library Data Access Application Block does not work in any Client Profile
- LINQ to SQL works correctly with SQL CE on the Client Profile
After creating a small console application with LINQ to SQL and SQL CE 3.5 all worked fine. Based on the How to: Deploy a SQL Server Compact Edition Database with an Application article on MSDN I deployed this small application to Windows XP running on a Virtual Machine with only a few Service Packs installed. Running the application raised an InvalidOperationException: Cannot open 'TestDatabase.sdf'. Provider 'System.Data.SqlServerCe.3.5' not installed.
When working with LINQ to SQL it wasn't sufficient to deploy the assemblies to the applciation folder, the application also required a provider for SQL Server CE. After a quick search I found the following topic on the MSDN forum: Can I XCopy SQL CE 3.5? yes and no, see message. In this topic someone described how you can create the provider using the App.config:
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SqlServerCe.3.5" />
<add name="Microsoft SQL Server Compact Data Provider"
invariant="System.Data.SqlServerCe.3.5"
description=".NET Framework Data Provider for Microsoft SQL Server Compact"
type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=3.5.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
</DbProviderFactories>
</system.data>
Good solution, but I would have preferred to set this in code without having to depend on the App.config. Since there is no other way to manipulate the DbProviderFactories I decided to create a wrapper around the configuration section that allows you to take the required actions in code.
Description classes
Before jumping right into the wrapper (a repository actually) take a look at the following code:
public class DbProviderFactoryDescription
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the invariant.
/// </summary>
/// <value>The invariant.</value>
public string Invariant { get; set; }
/// <summary>
/// Gets or sets the description.
/// </summary>
/// <value>The description.</value>
public string Description { get; set; }
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public string Type { get; set; }
/// <summary>
/// Initialize the description.
/// </summary>
public DbProviderFactoryDescription()
{
}
/// <summary>
/// Initialize the description.
/// </summary>
/// <param name="name"></param>
/// <param name="description"></param>
/// <param name="invariant"></param>
/// <param name="type"></param>
public DbProviderFactoryDescription(string name, string description, string invariant, string type)
{
this.Name = name;
this.Description = description;
this.Invariant = invariant;
this.Type = type;
}
/// <summary>
/// Initialize the description based on a row.
/// </summary>
/// <param name="row">The row.</param>
internal DbProviderFactoryDescription(DataRow row)
{
this.Name = row[0] != null ? row[0].ToString() : null;
this.Description = row[1] != null ? row[1].ToString() : null;
this.Invariant = row[2] != null ? row[2].ToString() : null;
this.Type = row[3] != null ? row[3].ToString() : null;
}
}
/// <summary>
/// Db Provider Description for Sql CE 3.5
/// </summary>
public class SqlCe35ProviderFactoryDescription : DbProviderFactoryDescription
{
public const string ProviderName = "Microsoft SQL Server Compact Data Provider";
public const string ProviderInvariant = "System.Data.SqlServerCe.3.5";
public const string ProviderDescription = ".NET Framework Data Provider for Microsoft SQL Server Compact";
public const string ProviderType = "System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe";
/// <summary>
/// Initialize the description.
/// </summary>
public SqlCe35ProviderFactoryDescription()
: base(ProviderName, ProviderDescription, ProviderInvariant, ProviderType)
{
}
}
The DbProviderFactoryDescription class is a POCO representation of the DbProviderFactory you can find in the App.config. And the SqlCe35ProviderFactoryDescription is a specific implementation for SQL CE 3.5. The invariant and type properties are the ones that actually define your provider. The invariant property is the real name or code of your provider, and the type property is the fully qualified type name of the factory that can create the provider.
In the DbProviderFactoryDescription you can also find an internal constructor that accepts a DataRow. This constructor will be used in the repository to convert the DataRow retrieved from the App.config to a DbProviderFactoryDescription object.
The repository
To manage these DbProviderFactories (or actually the DbProviderFactoryDescriptions) I created a repository that allows you to create new providers, delete existing providers, get a list of all providers and find a provider based on the invariant (the actual name of the provider). Note that creating a provider will delete any existing provider with the same invariant.

public class DbProviderFactoryRepository
{
/// <summary>
/// The table containing all the data.
/// </summary>
private DataTable dbProviderFactoryTable;
/// <summary>
/// Name of the configuration element.
/// </summary>
private const string DbProviderFactoriesElement = "DbProviderFactories";
/// <summary>
/// Initialize the repository.
/// </summary>
public DbProviderFactoryRepository()
{
OpenTable();
}
/// <summary>
/// Opens the table.
/// </summary>
private void OpenTable()
{
// Open the configuration.
var dataConfiguration = ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
if (dataConfiguration == null)
throw new InvalidOperationException("Unable to open 'System.Data' from the configuration");
// Open the provider table.
if (dataConfiguration.Tables.Contains(DbProviderFactoriesElement))
dbProviderFactoryTable = dataConfiguration.Tables[DbProviderFactoriesElement];
else
throw new InvalidOperationException("Unable to open the '" + DbProviderFactoriesElement + "' table");
}
/// <summary>
/// Adds the specified provider.
/// </summary>
/// <param name="provider">The provider.</param>
public void Add(DbProviderFactoryDescription provider)
{
Delete(provider);
dbProviderFactoryTable.Rows.Add(provider.Name, provider.Description, provider.Invariant, provider.Type);
}
/// <summary>
/// Deletes the specified provider if present.
/// </summary>
/// <param name="provider">The provider.</param>
public void Delete(DbProviderFactoryDescription provider)
{
var row = dbProviderFactoryTable.Rows.Cast<DataRow>()
.FirstOrDefault(o => o[2] != null && o[2].ToString() == provider.Invariant);
if (row != null)
{
dbProviderFactoryTable.Rows.Remove(row);
}
}
/// <summary>
/// Gets all providers.
/// </summary>
/// <returns></returns>
public IEnumerable<DbProviderFactoryDescription> GetAll()
{
return dbProviderFactoryTable.Rows.Cast<DataRow>()
.Select(o => new DbProviderFactoryDescription(o));
}
/// <summary>
/// Get provider by invariant.
/// </summary>
/// <param name="invariant"></param>
/// <returns></returns>
public DbProviderFactoryDescription GetByInvariant(string invariant)
{
var row = dbProviderFactoryTable.Rows.Cast<DataRow>()
.FirstOrDefault(o => o[0] != null && o[0].ToString() == invariant);
if (row != null)
{
return new DbProviderFactoryDescription(row);
}
else
{
return null;
}
}
}
The only important action in this class takes place in the OpenTable method, where the system.data section of the App/Web.config is opened as a DataSet. And from this DataSet we access the DbProviderFactories DataTable which in turn allows us to interact with the factories. Although this code uses a ConfigurationSection from the ConfigurationManager you do not need to add anything to the App.config yourself. We are using this ConfigurationSection because methods like DbProviderFactories.GetFactory() use this ConfigurationSection to find all factories.
Putting the repository to good use
This is an example of how you can create a DbProviderFactory for SQL Server Compact Edition 3.5:
// Initialize the repository.
var repository = new DbProviderFactoryRepository();
// Create a description manually and add it to the repository.
var manualDescription = new DbProviderFactoryDescription();
manualDescription.Description = ".NET Framework Data Provider for Microsoft SQL Server Compact";
manualDescription.Invariant = "System.Data.SqlServerCe.3.5";
manualDescription.Name = "Microsoft SQL Server Compact Data Provider";
manualDescription.Type = "System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe";
repository.Add(manualDescription);
// Use the default SqlCe35 provider.
repository.Add(new SqlCe35ProviderFactoryDescription());
Enjoy...