Tag Archives: C#

Entity Framework “In Code” konfigurieren

Wird das Entity Framework (kurz EF) über NuGet installiert, so werden im “App.config” diverse EF spezifische Konfigurationseinträge angelegt. Es gibt jedoch Szenarien, da sollen diese Konfigurationseinträge nicht im “App.config” oder “Web.config” vorkommen, sondern mittels Code gesetzt werden. Denn die Einträge im “App.config” oder “Web.config” verlangen zwangsläufig eine Referenz auf das EF im jeweiligen Project.

Ein mögliches Szenario ist, dass eine austauschbare Komponente das EF für den Datenzugriff verwendet. Die Komponente selbst soll dann für die Konfiguration des EFs zuständig sein.

Das folgende Bild zeige eine Applikation mit einer 3-Layer Architektur. Der UI-Layer beinhaltet die App.config-Datei. Der Core-Layer enthält sämtliche Bussines Logik. Der Data-Layer ist für den Datenzugriff zuständig und bietet drei Komponenten an. Eine der Komponenten greift auf Webservices zu, einer verwendet einen In Memory Speicher und einer verwendet das Entity Framework für den Zugriff auf eine (SQL) Datenbank. Die drei Komponenten können zur Design- oder Laufzeit ausgetauscht werden (beispielsweise unter Verwendung eines IoC-Containers).

Untitled

Der rote Pfeil “App.config” symbolisiert die nicht gewollte Referenz. Damit diese Referenz verhindert werden kann, wird das EF explizit im Code konfiguriert. Dafür wird eine Klasse erstellt welche von der Klasse “DbConfiguration” ableitet. Diese Konfiguration wird zur Laufzeit vom Entity Framework über Reflection geladen. Sie enthält die Konfiguration welche sich üblicherweise im “App.config” befindet.

Das folgende Code-Beispiel zeigt eine Klasse welche von “DbConfiguration” ableitet und das EF für die Verwendung einer SQLite-Datenbank konfiguriert.

using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Common;
using System.Data.SQLite;
using System.Data.SQLite.EF6;

namespace Data.SqliteStorage
{
	/// <summary>
	/// Konfiguriert das Entity Framework zur Verwendung mit SQLite.
	/// Diese Klasse wird automatisch instanziiert, weil von sie von <see cref="DbConfiguration"/> abgeleitet ist.
	/// Die Konfiugration stellt sicher, dass keine Anpassungen an einer Web.config oder App.config Datei nötig sind.
	/// </summary>
	public class SqLiteDbConfiguration : DbConfiguration
	{
		private const string DbFileName = "db.sqlite3";

		/// <summary>
		/// Eine <see cref="DbConnection"/> zur SQLite-Datenbank.
		/// </summary>
		/// <value>
		/// Die Connection.
		/// </value>
		public static DbConnection Connection { get; } = new SQLiteConnection(GetConnectionString(), true);

		public SqLiteDbConfiguration()
		{
			// Das Entity Framework wird in dieser Applikation immer mit SQLite benützt
			// Es ist kein Umschalten in der Konfiguration (web.config oder app.config) angedacht.
			SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
			SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
			SetProviderServices("System.Data.SQLite", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
		}

		private static string GetConnectionString()
		{
			// foreign key=true aktiviert die FK-Constraints
			return "Data Source=" + GetFilePath() + ";foreign keys=true";
		}

		private static string GetFilePath()
		{
			return "|DataDirectory|" + DbFileName;
		}
	}
}

SQLite, EntityFramework und Cascade Delete

SQLite bzw. eine SQLite Datenbank unterstützt, um die referentielle Integrität sicherzustellen, eine das Konstrukt einer Löschweitergabe (“ON DELETE CASCADE” beim erstellen eines Fremdschlüssels).

Während diese Löschweitergabe mit einem Tool z.B. SQLite Studio wie erwartet funktioniert, passiert beim Einsatz des Entity Frameworks nichts.

Die Ursache dieses Verhaltens ist, dass SQLite aus Kompatibilitätsgründen die Foreign Key Constraints ignoriert. Mehr dazu hier.

Man kann, im Falle von ADO.NET bzw. Entity Framework, die Foreign Key Constraints über den Connection String einschalten. Das kann mit dem Flag “foreign keys=true” gemacht werden.

Hier ein Beispiel, eines ConnectionStrings, ohne das entsprechende Flag:

<connectionStrings>
  <add name="ApplicationDbContext" connectionString="data source=|DataDirectory|\data.sqlite3" providerName="System.Data.SQLite" />
</connectionStrings>

Und hier eines mit eingeschaltenen Foreign Key Constraints:

<connectionStrings>
  <add name="ApplicationDbContext" connectionString="data source=|DataDirectory|\data.sqlite3;foreign keys=true" providerName="System.Data.SQLite" />
</connectionStrings>

Entity Framework CodeFirst für SQLite

Der ORM Mapper aus dem Hause Microsoft namens “Entity Framework” unterstützt ein sehr nützliches und häufig verwendetes Feature bzw. Ansatz namens “CodeFirst”.
“CodeFirst” ist nichts anderes als die automatische Generierung einer (SQL)-Datenbank, basierend auf dem geschrieben Code (Model). Dabei wird auf convention over configuration gesetzt und so generiert der folgende Code eine Datenbank mit zwei Tabellen inkl. Primary- und Foreign-Keys.

public class Player
{
	public int Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public Team Team { get; set; }
}

public class Team
{
	public int Id { get; set; }
	public string Name { get; set; }
	public ICollection<Player> Players { get; set; }
}

In einem laufenden Projekt, an dem ich mitarbeite, soll eine SQLite Datenbank einsetzt werden.

SQLite ist eine Programmbibliothek, die ein relationales Datenbanksystem enthält. SQLite unterstützt einen Grossteil der im SQL-92-Standard festgelegten SQL-Sprachbefehle. Unter anderem implementiert SQLite Transaktionen, Unterabfragen (subselects), Sichten (views), Trigger und benutzerdefinierte Funktionen.

Quelle: Wikipedia

Der Datenbank Zugriff wird mit dem Entity Framework realisiert. Die Entity Framework Unterstützung für SQLite lässt sich über ein NuGet Package hinzufügen: https://www.nuget.org/packages/System.Data.SQLite.

Leider unterstützt SQLite bzw. das SQLite NuGet-Package den CodeFirst-Ansatz nicht. Über diesen Post bin ich auf ein Stück Code gestossen, dass rudimentär den CodeFirst Ansatz implementiert: https://gist.github.com/flaub/1968486e1b3f2b9fddaf

Da ich für das Projekt noch ein paar weitere Funktionalitäten hinzufügen musste und der Code produktiv eingesetzt wird, habe ich beschlossen ein Refactoring durchzuführen und diesen Code wiederum auf GitHub zu veröffentlichen.

Das Resultat findet sich hier:
SQLite CodeFirst
Was alles unterstützt wird und wie die Library verwendet werden kann, ist im GitHub ReadMe beschrieben: Zum ReadMe.

Dynamics CRM API: E-Mail von Template erstellen

Das CRM bietet die Möglichkeit, E-Mail Templates zu erstellen. Basierend auf diesen Templates können dann neue E-Mails erstellt werden. Das Funktioniert natürlich auch über die API.

Als erstes der Code um eine E-Mail Template bei gegebenem Namen zu holen. Nebst dem Namen wird auch noch der TypeCode berücksichtigt. Der TypeCode ist nichts anderes als der Schemaname der Entität, für die das Template erstellt wurde.

private Guid GetTemplateIdByName(string templateName, string templateTypeCode)
{
    var query = new QueryByAttribute("template");
    query.AddAttributeValue("title", templateName);
    query.AddAttributeValue("templatetypecode", templateTypeCode);
    return organizationService.RetrieveMultiple(query).Entities.Single().Id;
}

In einem zweiten Schritt wird vom Template, mit Hilfe des “InstantiateTemplateRequest”, eine neue E-Mail erstellt. Das heisst, es wird ein neuer Record vom der Entity “E-Mail” im Response zurückgegeben. Dieser Record wurde jedoch im CRM erstellt. Der InstantiateTemplateRequest erwartet die folgenden Properties:

  • ObjectI: Die Id des Records für den die E-Mail erstellt werden soll
  • ObjectType: Der Name des Records für den die E-Mail erstellt werden soll
  • TemplateId: Die Id des Templates welches verwendet werden soll
private Email CreateEmailFromTemplate(Entity regardingEntity, string templateName)
{
    var templateId = GetTemplateIdByName(templateName, "contact");

    var request = new InstantiateTemplateRequest
    {
        ObjectId = regardingEntity.Id,
        ObjectType = regardingEntity.LogicalName,
        TemplateId = templateId
    };

    var repsonse = (InstantiateTemplateResponse)organizationService.Execute(request);
    return repsonse.EntityCollection.Entities.Single().ToEntity<Email>();
}

Schlussendlich kann die, vom Template generierte, E-Mail bearbeitet (z.B. Hinzufügen Empfänger) und mit einem “CreateRequest” erstellt werden. Wie ich dieser E-Mail dann ein Attachment hinzufügen und sie schlussendlich versenden kann, zeige ich in meinem Post von nächster Woche.

var email = CreateEmailFromTemplate(myCase, "myTemplate")
email.Id = organizationService.Create(email);

Outlook & C# Serie – Introduction

In meinem letzten privaten Projekt habe ich als PoC einen Prototypen gebaut welcher den Windows Live (oder Outlook.com) Kalender mit Outlook 2013 synchronisiert. Dabei bin ich auf der Outlook 2013 Seite auf einige “Hindernisse” gestossen. Diese Hindernisse und natürlich wie sie zu überwinden sind, stelle ich in der “Outlook & C# Serie” vor.

Mit diesem Post wird erst einmal der Grundstein gelegt. Jeder Anfang ist schwer, deshalb ganz allgemein: Wie hole ich Daten aus meinem Outlook?

Es ist egal ob ein Add-in geplant ist oder ob von einer externen Applikation bsp. WPF auf Outlook Elemente zugegriffen werden soll, der Code ist derselbe. Dafür wird folgendes benötigt.

  1. VSTO (Visual Studio Tools for Office) Installieren:
    http://www.microsoft.com/en-us/download/details.aspx?id=23656

  2. Referenz hinzufügen
    Falls nun ein Add-in geschrieben werden soll, einfach ein Projekt des entsprechenden Typs erstellen. In diesem Fall soll jedoch eine externe Applikation entwickelt werden. Dafür wird ein neues Projekt erstellt und die folgende DLL referenziert:
    C:Program Files (x86)Microsoft Visual Studio 12.0Visual Studio Tools for OfficePIAOffice15Microsoft.Office.Interop.Outlook.dll

  3. Zugriff auf Outlook
    Um Zugriff auf das Outlook Objekt modell zu erhalten wird eine neue Instanz der folgenden Klasse erstellt “Microsoft.Office.Interop.Outlook.Application”.

Outlook ist in Folder organisiert. Hier ein Beispiel wie der Kalender Folder geholt werden kann:

var appointmentsFolder = (Folder)outlook.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);

Eine Übersicht über das Objektmodell gibt es hier: http://msdn.microsoft.com/en-us/library/ms268893.aspx