Entity Framework 6 устанавливает время выполнения строки подключения
Мы находимся в смешанной среде, где наше приложение использует как ADO.NET, так и Entity Framework.
Поскольку оба указывают на один и тот же физический SQL-сервер, мы хотели бы удалить строку подключения Entity Framework из файла конфигурации и затем автоматически построить строку на основе текущих строк соединения ADO.NET.
Это избавит нас от ошибок, когда разработчик изменил строку ADO.NET, но забыл изменить строку подключения Entity Framework.
Я прочитал это, но они не ответили на вопрос.
Как создать строку соединения программно в MS SQL в Entity Framework 6?
Если я создаю свой собственный DbConnection и передаю его в DbContext (existingConnection, contextOwnsConnection), тогда он выдает ошибку "Контекст используется в режиме Code First с кодом, который был сгенерирован из файла EDMX для базы данных First или Model Первая разработка".
Я не использую Code First.
https://msdn.microsoft.com/en-us/data/jj680699
Это говорило о конфигурации базы кода в EF 6, но в статье не отображается код, который фактически изменил строку соединения.
ОБНОВЛЕНО: дополнительная информация, чтобы помочь уточнить мой вопрос.
Я НЕ использую первый код и хотел бы построить строку подключения за пределами файла конфигурации.
DbContext, который я использую, является частичным классом для автоматически созданного файла DbContext, который генерирует шаблон T4.
У меня создалось впечатление, что мне нужно создать унаследованный класс DbConfiguration и сделать что-то в этом классе, но единственным примером, который я нахожу, является использование Azure.
https://msdn.microsoft.com/en-us/data/jj680699
Существует статья о Code Project, в которой говорится о настройке строки соединения во время выполнения, но статья основана на построении строки подключения каждый раз, когда я создаю новый контейнер Entity.
http://www.codeproject.com/Tips/234677/Set-the-connection-string-for-Entity-Framework-at
Я хотел бы иметь возможность использовать мой частичный класс DbContext для создания строки подключения, чтобы вызывающий абонент не должен был делать что-либо особенное.
ОБНОВЛЕНО: Рабочий код для RunTime, но не DesignTime
Используя код, отправленный @Circular Reference, перечисленный ниже, я смог изменить строку соединения, не меняя вызовы на мой класс Entity, но это не работает для файла DesignTime EDMX.
public partial class TestEntities : DbContext
{
public TestEntities() : base(GetSqlConnection(), true)
{
}
public static DbConnection GetSqlConnection()
{
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
var connectionSettings = ConfigurationManager.ConnectionStrings("Current_ADO_Connection_In_Config");
// Set the provider name.
entityBuilder.Provider = connectionSettings.ProviderName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = connectionSettings.ConnectionString;
// Set the Metadata location.
entityBuilder.Metadata = "res://*/Models.TestModel.csdl|res://*/Models.TestModel.ssdl|res://*/Models.TestModel.msl";
return new EntityConnection(entityBuilder.ToString());
}
}
Теперь, если я могу просто запустить DesignTime, тогда это будет хорошо.
Ответы
Ответ 1
Вы получаете исключение режима Code First, потому что вы передаете DbConnection
, построенный с помощью строки подключения ADO.NET. Эта строка подключения не содержит ссылок на файлы метаданных, поэтому EntityFramework не знает, где их найти.
Чтобы создать DbContext
с соответствующей программно заданной строкой соединения, используйте класс EntityConnectionStringBuilder.
var entityBuilder = new EntityConnectionStringBuilder();
// use your ADO.NET connection string
entityBuilder.ProviderConnectionString = conString;
// Set the Metadata location.
entityBuilder.Metadata = @"res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl";
var dbContext = new DbContext(entityBuilder.ConnectionString);
Ответ 2
Вы можете работать во время разработки, используя строку подключения в вашем файле конфигурации.
<add name="DWContext" connectionString="metadata=res://*/Database.DWH.DWModel.csdl|res://*/Database.DWH.DWModel.ssdl|res://*/Database.DWH.DWModel.msl;provider=System.Data.SqlClient;provider connection string="data source=SQLSERVER_INSTANCE;initial catalog=DB_NAME;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Так что не удаляйте его, потому что он вам нужен ТОЛЬКО во время разработки.
Вместо этого используйте динамический путь во время выполнения с использованием этого подхода (аналогично вашему последнему):
Расширить частичный класс контекста данных:
public partial class DWContext
{
public DWContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
/// <summary>
/// Create a new EF6 dynamic data context using the specified provider connection string.
/// </summary>
/// <param name="providerConnectionString">Provider connection string to use. Usually a standart ADO.NET connection string.</param>
/// <returns></returns>
public static DWContext Create(string providerConnectionString)
{
var entityBuilder = new EntityConnectionStringBuilder();
// use your ADO.NET connection string
entityBuilder.ProviderConnectionString = providerConnectionString;
entityBuilder.Provider = "System.Data.SqlClient";
// Set the Metadata location.
entityBuilder.Metadata = @"res://*/Database.DWH.DWModel.csdl|res://*/Database.DWH.DWModel.ssdl|res://*/Database.DWH.DWModel.msl";
return new DWContext(entityBuilder.ConnectionString);
}
}
И из вашего кода создайте новый контекст данных EF с помощью:
private DWContext db = DWContext.Create(providerConnectionString);
Ciao; -)