实体框架代码首先没有app.config [英] Entity Framework Code First without app.config

查看:184
本文介绍了实体框架代码首先没有app.config的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望有人能够帮助我,因为它似乎完全卡住了。



对于我们公司的即将到来的项目,我们想使用实体框架5采用代码第一种方法。我玩了一会儿,每次我尝试使用EF与我们现有的图书馆,我失败了,因为它似乎EF很大程度上依赖于一个现有的app.config。



在我们公司,我们有一个内部数据库库,使我们可以连接到各种数据源和数据库技术,从而获得数据库提供者的MEF(受管理的扩展性框架)的优势。我只需要传递一些数据库设置,如主机(或文件),目录,用户凭据和数据库提供程序名称,该库将查找相应的插件,并返回一个自定义连接字符串或IDbConnection。
我们想与EF一起使用这个库,因为它允许我们灵活地使用我们使用的数据库,也可以在运行时更改数据库。



所以。我看到一个典型的DbContext对象在构造函数中没有参数。它会在app.config中自动查找适当的连接字符串。我们不喜欢这样的东西,所以我改变了默认的构造函数来获取一个DbConnection对象,该对象被传递给了DbContext基类。没有交易。



当代码第一个模型发生变化时,会出现问题。 EF自动注意到这一点,并寻找迁移类/配置。但是:典型的迁移类需要一个默认的无参数的上下文构造函数!很可惜!



所以我们使用IDbContextFactory接口构建我们自己的迁移类。但是再次看来,这个IDbContextFactory似乎需要一个无参数的构造函数,否则我无法添加迁移或更新数据库。



此外,我创建了自己的数据迁移配置器,我通过上下文,也是目标数据库。问题是:没有找到任何迁移类,无论我尝试什么。



我完全卡住了,因为它似乎是使用EF的唯一方法是连接字符串保存在app.config中。这是愚蠢的,因为我们需要在运行时更改数据库连接,而app.config是默认用户的只读。



如何解决这个问题?

解决方案

答案在这里提供



https://stackoverflow.com/a/15919627/941240



诀窍是稍微修改默认的 MigrateDatabaseToLatestVersion 初始化器使得:




  • 数据库始终被初始化...

  • ...使用当前上下文中的连接字符串



DbMigrator 仍然会创建一个新的数据上下文,但会根据初始化程序从连接字符串复制上下文。我甚至可以缩短代码。



这里它是:

  public class MasterDetailContext:DbContext 
{
public DbSet< Detail>细节{get;组; }
public DbSet< Master>大师{get;组; }

//这个DbMigrator使用的 - 我不会在我的代码中使用它
public MasterDetailContext()
{
Database.Initialize(true );
}

//相当于 - 我要使用这个,我想要动态连接字符串
public MasterDetailContext(string ConnectionString):base(ConnectionString)
{
Database.SetInitializer(new CustomInitializer());
Database.Initialize(true);
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove< PluralizingTableNameConvention>();
}
}

public class CustomInitializer:IDatabaseInitializer< MasterDetailContext>
{

#region IDatabaseInitializer< MasterDetailContext>成员

//通过从上下文复制连接字符串
修复MigrateDatabaseToLatestVersion
的问题public void InitializeDatabase(MasterDetailContext context)
{
配置cfg = new Configuration(); //迁移配置类
cfg.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString,System.Data.SqlClient);

DbMigrator dbMigrator = new DbMigrator(cfg);
//这将调用datacontext
//的无参数构造函数,但是从
dbMigrator.Update()开始,上面的连接字符串将被设置。
}

#endregion
}

客户端代码:

  static void Main(string [] args)
{

using MasterDetailContext ctx = new MasterDetailContext(@Database = ConsoleApplication801; Server = .\SQL2012; Integrated Security = true))
{
}

使用(MasterDetailContext ctx = new MasterDetailContext(@Database = ConsoleApplication802; Server = .\SQL2012; Integrated Security = true)
{
}
}
pre>

运行此操作将导致根据迁移配置创建和迁移两个数据库。


I hope somebody is able to help me, because it seems I'm totally stuck.

For upcoming projects in our company we'd like to use Entity Framework 5 with an code first approach. I played around a little while and everytime I try to use EF with our existing libraries, I fail because it seems EF heavily relies on an existing app.config.

In our company, we have an inhouse database library that allows us to connect to various data sources and database technologies taking the advantages of MEF (managed extensibility framework) for database providers. I just have to pass some database settings, such as host (or file), catalog, user credentials and a database provider name, the library looks for the appropriate plugin and returns me a custom connection string or IDbConnection. We'd like to use this library together with EF because it allows us to be flexible about which database we use also change the database at runtime.

So. I saw that a typical DbContext object takes no parameters in the constructor. It automatically looks for the appropriate connection string in app.config. We don't like such things so I changed the default constructor to take a DbConnection object that get's passed to the DbContext base class. No deal.

Problems occur when the code first model changes. EF automatically notices this and looks for migration classes / configuration. But: A typical migration class requires a default parameterless constructor for the context! What a pity!

So we build our own migration class using the IDbContextFactory interface. But again, it seems that also this IDbContextFactory needs a parameterless constructor, otherwise I'm not able to add migrations or update the database.

Further, I made my own data migration configurator where I pass the context, also the target database. Problem is here: It doesn't find any migration classes, no matter what I try.

I'm completely stuck because it seems the only way to use EF is when connection strings are saved in app.config. And this is stupid because we need to change database connections at runtime, and app.config is read-only for default users!

How to solve this?

解决方案

The answer is provided here

https://stackoverflow.com/a/15919627/941240

The trick is to slightly modify the default MigrateDatabaseToLatestVersion initializer so that:

  • the database is always initialized ...
  • ... using the connection string from current context

The DbMigrator will still create a new data context but will copy the connection string from yours context according to the initializer. I was even able to shorten the code.

And here it goes:

public class MasterDetailContext : DbContext
{
    public DbSet<Detail> Detail { get; set; }
    public DbSet<Master> Master { get; set; }

    // this one is used by DbMigrator - I am NOT going to use it in my code
    public MasterDetailContext()
    {
        Database.Initialize( true );
    }

    // rather - I am going to use this, I want dynamic connection strings
    public MasterDetailContext( string ConnectionString ) : base( ConnectionString )
    {
        Database.SetInitializer( new CustomInitializer() );
        Database.Initialize( true );
    }

    protected override void  OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

public class CustomInitializer : IDatabaseInitializer<MasterDetailContext>
{

    #region IDatabaseInitializer<MasterDetailContext> Members

    // fix the problem with MigrateDatabaseToLatestVersion 
    // by copying the connection string FROM the context
    public void InitializeDatabase( MasterDetailContext context )
    {            
        Configuration cfg = new Configuration(); // migration configuration class
        cfg.TargetDatabase = new DbConnectionInfo( context.Database.Connection.ConnectionString, "System.Data.SqlClient" );

        DbMigrator dbMigrator = new DbMigrator( cfg );
        // this will call the parameterless constructor of the datacontext
        // but the connection string from above will be then set on in
        dbMigrator.Update();             
    }

    #endregion
}

Client code:

    static void Main( string[] args )
    {

        using ( MasterDetailContext ctx = new MasterDetailContext( @"Database=ConsoleApplication801;Server=.\SQL2012;Integrated Security=true" ) )
        {
        }

        using ( MasterDetailContext ctx = new MasterDetailContext( @"Database=ConsoleApplication802;Server=.\SQL2012;Integrated Security=true" ) )
        {
        }
    }

Running this will cause the two databases to be created and migrated according to the migration configuration.

这篇关于实体框架代码首先没有app.config的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆