Статьи

Entity Framework 6 и SQL Server Compact 4 (2) — Простое развертывание частного рабочего стола

В этой статье я опишу упрощенный подход к развертыванию частного рабочего стола SQL Server Compact с помощью Entity Framework 6, а обзорную статью блога по частному развертыванию с SQL Server Compact см. В моем  блоге здесь .

При использовании Private Deployment с Entity Framework 6 из-за того, что EntityFramework.SqlServerCompact также устанавливает пакет SQL Server Compact NuGet, мы должны использовать немного иной подход, чем я описал  здесь  , чтобы упростить задачу. Основное отличие состоит в том, что мы должны заставить проект использовать целевую платформу x86 вместо AnyCPU (или AnyCPU, предпочитают 32-разрядную версию). Это связано с тем, что при запуске Prefer 32 bit поставщик SQL Server Compact ADO.NET загружает неправильные файлы, поскольку PROCESSORPLATFORM в этом случае остается AMD64 на 64-разрядных системах, но исполняемый .NET Framework — версия x86.

Чтобы узнать больше о новой целевой опции платформы по умолчанию, представленной в .NET 4.5, см.  Документацию MSDN  здесь и пост в  блоге здесь .

Кроме того, я покажу, как использовать набор инструментов SQL Server Compact для быстрого начала работы с рабочим процессом Database First.

Для простоты и для того, чтобы сосредоточить внимание на аспектах частного развертывания, я продемонстрирую на консольном приложении, но тот же подход будет работать и для приложений WinForms и WPF. Подход НЕ будет работать для выходных проектов DLL, таких как, например, надстройки и аналогичные, так как он опирается на записи конфигурации в app.config. И этот блог посвящен развертыванию, а не многоуровневой архитектуре. 

Короче, нам нужно сделать следующее:

1. Создайте проект и установите для Target Platform значение x86.

2. Добавьте пакет NuGet EntityFramework.SqlServerCompact.PrivateConfig в проект.

3: Добавить файл нашей базы данных в качестве содержимого проекта

4. Создайте EDMX (или классы First Code) и настройте строку подключения.

5. Добавьте код для правильного развертывания файла базы данных во время запуска приложения.

Но давайте подробно рассмотрим каждую задачу ниже.

Прежде чем начать, убедитесь, что у вас установлено следующее:

1: Visual Studio 2013 Pro или выше.

2: последняя версия моей надстройки SQL Server Compact Toolbox (установка через инструменты / расширения в VS). Для панели инструментов требуется установить среды выполнения SQL Server Compact 3.5 SP2 и 4.0 SP1 (требование 3.5 будет отменено в следующей версии Toolbox)

3: Существующий файл базы данных SQL Server Compact, я буду использовать Chinook

После этого давайте откроем Visual Studio и начнем:

Создать новое консольное приложение

Перейдите в Файл, Новый проект и создайте новое консольное приложение Windows. Обязательно установите целевую платформу на 4.0 или новее.

image_thumb3

Теперь установите Target Platform на x86 ( это важный шаг,  если вы забудете это сделать, вы получите исключение BadImageFormat во время выполнения / отладки)

Перейдите в свойства проекта и выберите раздел / вкладку «Построение» и выберите x86:

образ

Установите Entity Framework 6 из NuGet

Чтобы получить последнюю и лучшую 6-битную версию Entity Framework, всегда устанавливайте ее с NuGet. А благодаря удивительным функциям разрешения зависимостей пакетов в NuGet достаточно установить один необходимый пакет, а остальные пакеты будут установлены как зависимости. В этом случае единственное, чего не хватает в пакете EntityFramework.SqlServerCompact (зависит от SQL Server Compact 4 и EF6), — это регистрация DbProvider в файле app.config, которая позволяет работать без установленной среды выполнения SQL Server Compact. в GAC и machine.config. Чтобы исправить эту «недостающую ссылку», я создал http://www.nuget.org/packages/EntityFramework.SqlServerCompact.PrivateConfig/ 

пакет, который просто добавляет отсутствующие записи конфигурации и, в свою очередь, зависит от всех других необходимых пакетов. Это добавляет это в файл app.config:

  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SqlServerCe.4.0" />
      <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
    </DbProviderFactories>
  </system.data>

Другими словами, просто установите пакет EntityFramework.SqlServerCompact.PrivateConfig. Щелкните правой кнопкой мыши папку «Ссылки» в своем проекте и выберите «Управление пакетами NuGet». Найдите имя пакета и установите его. И все необходимые пакеты и ссылки будут установлены. (Я работаю  над  добавлением этих записей конфигурации в базовый пакет EntityFramwork.SqlServerCompact, чтобы упростить работу)

Добавьте файл вашей базы данных в проект 

Я буду использовать Chinook, который вы можете установить с NuGet. Но, конечно, не стесняйтесь использовать свой собственный файл базы данных. 

Найдите пакет базы данных Chinook SQL Server Compact и установите его: 

образ

Обязательно пометьте файл базы данных как Content, Copy Always в проекте. Позже я опишу в этом посте, как правильно разместить его на компьютере конечного пользователя.

образ

 Create the Entity Data Model (EDMX) and adjust the connection string

Build the project.

Now in the SQL Server Compact Toolbox, connect to the database file in your project folder:

образ

Right click the database, and select the “Add Entity Data Model (EDMX) to current project” menu item:

образ

Click OK, and the EDMX file and various other files will be added to your project:

образ

Build the project.

Now let us add some test code to the Main method in order to verify that everything works so far:

using (var context = new ChinookEntities())
{
    foreach (var album in context.Album.ToList())
    {
        Console.WriteLine(album.Title);
    }

}
Console.ReadKey();

We can now access the database via the generated object model, and do not have to type SQL, but can use LINQ to Entities to query the database. In addition, we can update the database (INSERT, UPDATE, DELETE) via methods on the derived DbContext class, ChinookEntities. In app.config, the following connection string has been added:

 <connectionStrings>
    <add name="ChinookEntities" connectionString="metadata=res://*/Chinook.csdl|res://*/Chinook.ssdl|res://*/Chinook.msl;provider=System.Data.SqlServerCe.4.0;provider connection string="Data Source=C:\Users\erik.COMMENTOR\Documents\Visual Studio 2013\Projects\ConsoleApplication4\Chinook.sdf""
      providerName="System.Data.EntityClient" />
  </connectionStrings>

In order to make the connection string user and folder independent, change the data source as follows:

<connectionStrings>
    <add name="ChinookEntities" connectionString="metadata=res://*/Chinook.csdl|res://*/Chinook.ssdl|res://*/Chinook.msl;provider=System.Data.SqlServerCe.4.0;provider connection string="Data Source=|DataDirectory|\Chinook.sdf""
      providerName="System.Data.EntityClient" />
  </connectionStrings>

Deploy the database file 

The final step will be done to ensure that the database file will be located in a writeable location on the users machine when deployed/installed. We will simply do this in code in order to not depend on any install actions and issues. We will use the same approach that I have already used in my blog post here, which takes advantage of the DataDirectory connection string macro. So add this piece of code to the Program class:

private const string dbFileName = "Chinook.sdf";
private static void CreateIfNotExists(string fileName)
{
    string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    // Set the data directory to the users %AppData% folder 
    // So the database file will be placed in: C:\\Users\\<Username>\\AppData\\Roaming\\ 
    AppDomain.CurrentDomain.SetData("DataDirectory", path);

    // Enure that the database file is present
    if (!System.IO.File.Exists(System.IO.Path.Combine(path, fileName)))
    {
        //Get path to our .exe, which also has a copy of the database file
        var exePath = System.IO.Path.GetDirectoryName(
            new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
        //Copy the file from the .exe location to the %AppData% folder
        System.IO.File.Copy(
            System.IO.Path.Combine(exePath, fileName),
            System.IO.Path.Combine(path, fileName));
    }
}

Remember to add a call to CreateIfNotExists as the first line in the Main method:

static void Main(string[] args)
{
    CreateIfNotExists(dbFileName);

You can now use ClickOnce, XCopy or an Installer to deploy your app (the files in the release folder), with no other requirements than the target .NET Framework version. Uninstall the 4.0 runtime from your PC in order to test (and/or test on another PC without SQL CE 4.0 installed)

What we have achieved:

— Simple, self contained deployment of a single user desktop app of any type to any .NET 4.0 or higher platform (not ARM, though)

— Automated creation of the required settings in app.config via NuGet packages

— RAD (Rapid App Development) “Database First” access to a well-performing, well-documented and powerful ORM.

You can download the complete solution (without packages) from here.