2016-10-26 6 views
0

Я начал хотеть генерировать код с помощью T4. Для этого мне нужны данные из базы данных. Поскольку все данные в проекте уже получены с использованием EF, я выбираю использовать EF. Итак, в рамках моего проекта я создал класс утилиты со статическим методом, который возвращает нужный мне объект. Я узнал, что работает в контексте настраиваемого инструмента T4, который я не могу прочитать из config. Поэтому я вручную установил строку подключения моего контекста, и это сработало!Структура и конфигурация сущности. Вызов из статического контекста

private static string GetConnectionString() 
    { 
     //How to read from the web.config when running a T4 template ? 
     //ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["XXXXXXX"]; 
     //var connectionString = settings.ConnectionString; 
     var connectionString = @"Data Source=XXXXXX;Initial Catalog=XXXXXX;Integrated Security=SSPI;MultipleActiveResultSets=true;"; 
     return connectionString; 
    } 

Позже я добавил проект в свое решение. Проект A содержит класс со статическим методом, который возвращает объект. Теперь из кода в Project B Я хочу назвать этот статический метод.

При запуске этого кода я получаю сообщение об ошибке: «Поставщик службы Entity Framework не найден для поставщика ADO.NET с инвариантным именем« System.Data.SqlClient ». Убедитесь, что поставщик зарегистрирован в разделе« entityFramework » приложение конфигурационный файл. См http://go.microsoft.com/fwlink/?LinkId=260882 для получения дополнительной информации. "

Когда я устанавливаю NuGet пакет EF для проекта B, код работает, как ожидалось. Но это бьет всю цель создания полезного класса в проекте A. Вызывающая сторона должна просто получать объект независимо от его собственного контекста.

Как это исправить? Как настроить статический метод для использования EF и сделать его доступным для использования в качестве ссылки на вызывающие стороны, не зная EF?

Я думаю, что ответ, вероятно, будет чем-то вроде переопределения поведения EF для чтения из статического контекста, предоставленного в классе утилиты, вместо конфигурации, предоставленной текущей средой выполнения. Но как вы можете это сделать?

+0

призвание (то есть тот, который на самом деле создает DbContext,) проект требует ссылки, так как конфигурация приложения читается в этом контексте. Я не знаю, поддерживается ли разделение функций конфигурации в этом отношении в EF. – DevilSuichiro

ответ

1

Если вы не хотите, чтобы добавить весь пакет EF, то просто добавьте ссылку на EntityFramework.SqlServer.dll в проекте В.

Даже если проект B ссылается Project A не будет копировать этот файл через потому, что он ссылается в файле конфигурации в секции EF.

<entityFramework> 
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> 
     <parameters> 
      <parameter value="mssqllocaldb" /> 
     </parameters> 
    </defaultConnectionFactory> 
    <providers> 
     <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> 
    </providers> 
    </entityFramework> 

Смотрите раздел провайдеров выше, это говорит рамки сущности, где найти поставщика вашего используете (System.Data.SqlClient)

+0

Кстати, фактическая проблема была решена долгое время, выбирая совершенно другой подход, который также удовлетворил желаемую функциональность пользователя. –

+0

Итак, какое полное решение? EF динамически загружает поставщиков, которые вы установили, но если у вас есть несколько проектов в цепочке ссылок и не добавьте ссылку на библиотеку SQLClient, она не будет скопирована в выходную папку. Я думаю, вы также можете использовать задачу пост-сборки и скопировать SQLClient lib таким образом, если вы действительно не хотите брать лишние ссылки, но это похоже на излишний плюс, и другим разработчикам будет сложно узнать, что происходит – Frank

0

Первая часть о шаблоне T4, я был в состоянии решить, установив ConnectionString вручную:

/// <summary> 
    /// When calling from a T4 template, it seems you cannot use the ConfigurationManager. 
    /// </summary> 
    /// <returns></returns> 
    private static string GetConnectionString() 
    { 
     var connectionString = string.Empty; 

     if (ConfigurationManager.ConnectionStrings["DBContext"] != null) 
     { 
      connectionString = ConfigurationManager.ConnectionStrings["DBContext"].ConnectionString; 
     } 
     else if (System.Reflection.Assembly.GetExecutingAssembly().GetName().Name == "MyApplication") 
     { 
      ExeConfigurationFileMap configToUse = null; 
      var possibleConfig = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config"; 
      if (File.Exists(possibleConfig)) 
      { 
       configToUse = new ExeConfigurationFileMap(); 
       configToUse.ExeConfigFilename = possibleConfig; 
       var config = ConfigurationManager.OpenMappedExeConfiguration(configToUse, ConfigurationUserLevel.None); 
       connectionString = config.ConnectionStrings.ConnectionStrings["DBContext"].ConnectionString; 
      } 
     }    
     return connectionString; 
    } 

создать System.Data.Entity.DbContext, используя этот ConnectionString и кормить его к GenericUnitOfWork. Теперь T4 может правильно запустить мой метод getData.

Когда я вызываю метод getData из другого проекта, я предоставляю connectionstring в качестве параметра. Но метод getData будет работать только правильно, если вызывающая сборка знает EntityFramework как ссылку.

Поэтому я добавил ссылку на EF в другом проекте. И это работает.

Но я все еще не удовлетворен: как настроить мой метод getData, чтобы вызывающая сборка не нуждалась в ссылке на EF? Я имею в виду, что это должно быть правильно?

+0

Даже это не работает! Возможный файл конфигурации: C: \ Workspaces \ My Application \ bin \ MyApplication.dll.config при отладке шаблона. BUT C: \ Users \ myuser \ AppData \ Local \ assembly \ dl3 \ LB1NKXJR.QT0 \ YX0JMA7K.4V3 \ f116a810 \ 623287ac_972fd201 \ MyApplication.dll.config при запуске шаблона. –