Aangepaste connectionstring in Entity Framework

Een klant van ons wilde dat ik de manier waarop Entity Framework 6.3 omgaat met database credentials in de connectionstring zou aanpassen. Normaal gesproken vind je deze gegevens, mits je niet Windows authenticatie gebruikt, samen met wat meta-informatie over het model in de connectionstring in de app.config. Wanneer je dus SQL authenticatie wilt gebruiken, staat de database user en wachtwoord dus gewoon leesbaar in het configuratiebestand. Deze zijn standaard niet versleuteld. De klant vond het geen prettig idee dat de gebruiker dit bestand met bijvoorbeeld Kladblok zou openen en deze gegevens dus kon bekijken. Er zijn een aantal methoden waarmee je de gegevens in de connectionstring kan verleutelen. De manier die in de standaard documentatie staat beschreven is echter zeer lastig te implementeren. Ik heb ervoor gekozen om de connectionstring op te bouwen in de constructor van de DbContext. Ik voeg eerst de volgende sleutels toe aan de sectie in de app.config. Je kunt zelf bepalen met welke encryptie methode je deze versleuteld.


 
 
   
   
   
   
   
   
 


Wanneer je binnen een database-first scenario werkt, zal de DbContext telkens weer gegenereerd worden wanneer het model wordt aangepast. Je wil echter voorkomen dat jouw code dus telkens weer wordt overschreven bij een database wijziging. Een oplossing hiervoor is het toepassen van een zogenaamde 'partial' class. Dit is een los bestand, met daarin een klasse definitie die gelijk is aan, in ons geval, de DbContext. Uitgaande dat mijn context MyDbContext.vb heet, voeg ik een nieuwe klasse toe met de naam MyDbContextPartial.vb. Ik voeg de code zoals hieronder is beschreven toe. Omdat de eerste regel in de constructor MyBase.New() is, moeten we een Shared methode aanmaken die voor de connectionstring gaat opbouwen. Dit is echter niet een connectionstring zoals je misschien op het eerste gezicht zou verwachten. Het is om precies te zijn een EntityConnectionString; deze bevat ook meta-data over het model dat in gebruik is. Deze informatie tref je ook aan in de connectionstring zoals hij nu ook al in de app.config te vinden is. Merk op dat de klasse is gemarkeerd als Partial.

 
Imports System.Configuration 
Imports System.Data.Entity.Core.EntityClient 
Imports System.Data.SqlClient 
   
Partial Public Class MyDbContext 
   
  Public Sub New() 
    MyBase.New(GetEntityConnectionString()) 
  End Sub 
   
  Private Shared Function GetEntityConnectionString() As String 
   
    Dim entityConnectionStringBuilder As New EntityConnectionStringBuilder() 
    With entityConnectionStringBuilder 
        .Provider = "System.Data.SqlClient" 
        .ProviderConnectionString = GetProviderConnectionString() 
        .Metadata = "res://*/EntitiesModel.csdl|" & 
                            "res://*/EntitiesModel.ssdl|" & 
                            "res://*/EntitiesModel.msl" 
    End With 
   
    Return entityConnectionStringBuilder.ToString() 
   
  End Function 
   
  Private Shared Function GetProviderConnectionString() As String 
   
    Dim userID = DecryptText(ConfigurationManager.AppSettings("UserID")) 
    Dim password = DecryptText(ConfigurationManager.AppSettings("Password")) 
   
    Dim sqlConnectionStringBuilder As New SqlConnectionStringBuilder() 
    With sqlConnectionStringBuilder 
      .DataSource = ConfigurationManager.AppSettings("ServerName").ToString() 
      .InitialCatalog = ConfigurationManager.AppSettings("DatabaseName").ToString() 
      .IntegratedSecurity = False 
      .UserID = userID 
      .Password = password 
    End With 
   
    Return sqlConnectionStringBuilder.ToString() 
   
  End Function 
   
End Class 


In dit voorbeeld gebruik ik voor het ontsleutelen de methode DecryptText(). Deze functionaliteit bevindt zich in een gedeelde library die wij ook voor deze klant hebben gemaakt. Je kunt natuurlijk elke encryptie methode gebruiken die jezelf wilt. Op het internet kun je veel voorbeelden vinden van hoe je dit zelf ook kunt doen. Het toevoegen van de extra klasse en logica is echter niet het enige wat je moet doen. Je moet in de bestaande MyDbContext klasse de constructor verwijderen. Deze constructor zal namelijk het standaard gedrag aanroepen en dat is juist wat we niet willen. 

 
Imports System 
Imports System.Data.Entity 
Imports System.Data.Entity.Infrastructure 
   
Partial Public Class MyDbContext 
   
  Inherits DbContext  
   
  Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder) 
    Throw New UnintentionalCodeFirstException() 
  End Sub 
   
  Public Overridable Property Customers() As DbSet(Of Customer) 
  Public Overridable Property Orders() As DbSet(Of Order) 
       
End Class 


Met deze code kun je zelf ook aangepaste connectionstrings ondersteunen in combinatie met Entity Framework.

Ik heb deze post eerder in het Engels gepubliceerd op mijn eigen blog: www.obelink.com

Nieuwsbrief

Blijf op de hoogte van alles wat op VBcentral gebeurd. Meld je nu aan voor onze nieuwsbrief! »

Over ons

Wij zijn gek op het Microsoft .NET ontwikkelplatform en haar ontwikkeltalen, maar we hebben een sterke voorkeur voor Visual Basic .NET! »

Neem contact op

VBcentral.nl
Bataafseweg 20
7101 PA Winterswijk
Nederland
+31 (543) 538 388
info@vbcentral.nl