如何让用户在C#EF4.1 Code First中动态指定数据库提供程序和连接细节?

时间:2013-03-27 19:26:05

标签: c# database ef-code-first connection-string

我正在创建一个C#应用程序来替换使用MySQL数据库的VB6应用程序,其中应用程序的多个副本使用相同的数据库。新的应用程序必须能够使用当前的MySQL数据库,但我也希望它与数据库无关,因此应用程序的未来实例可以使用用户想要的任何服务器。在一个完美的世界中,我希望首次运行的应用程序向用户显示一个对话框,让他们选择数据库类型(MySQL,SQL Server等)并指定服务器ip,用户,密码和数据库名称。然后,应用程序将连接到该服务器并使用数据库(如果已存在)或创建新数据库(如果不存在)。

使用Code First我已经理解了如何使用现有数据库或创建新数据库,但只能通过对App.config文件中的连接字符串进行硬编码。

    <add name="GumpIndexDatabase"
     connectionString="server=localhost;userid=123;password=123;port=3306;database=gump_new_data;pooling=false;"
     providerName="MySql.Data.MySqlClient"
     />

我可以在启动应用程序之前更改连接字符串和提供程序,一切都按预期工作。我也可以在启动后更改连接字符串,但不能更改提供程序,我必须知道提供程序是MySQL还是MSSQL才能获得正确的连接字符串详细信息(例如:user或userid)

class GumpIndexDatabase: DbContext
{
    public GumpIndexDatabase(string connectionName)
        : base(MakeConnectionString(connectionName))
    {
    }
    private static string MakeConnectionString(string connectionName)
    {
         if (connectionName=MySQL) {
             //return MySQL string
         } else {
             //return SQL Server string
         }
    }

搜索时间没有出现如何做这样的事情的例子,所以我怀疑它是不被允许或推荐的,即使它看起来像这么简单。我已经看到一些关于连接字符串构建器的文章,但是不了解如何从通用对象中获取特定于数据库的字符串。

所以简单的问题是:如何在运行时指定数据库连接细节?

2 个答案:

答案 0 :(得分:1)

我不建议强制执行此功能,除非你100%肯定你不能没有它。它增加了许多维护任务,这些任务目前可能并不明显(例如更新到更新的版本,修复错误,花费大量时间来找出通用接口,维护这些接口,大量的测试等等)。因此,除非它是一个要求的商业功能 - 忘了它。

但是,如果您知道自己在做什么,通常会通过接口解决此问题。可能有这些常见的接口(通过它来确定它们是一项任务):

  • IConnection
  • IDataProvider
  • IRepository<T>

目前,您将使用MySql数据库实现接口,例如class MySqlConnection : IConnection。如果您需要MS SQL,class MsSqlConnection : IConnection

有效地,您必须将所有功能抽象为通用接口。您必须为要支持的每个数据库/存储引擎提供实现。在运行时,您将使用IoC容器和DI原则来设置当前实现。所有子依赖项都将使用作为参数传入的接口到构造函数(或属性或方法)

答案 1 :(得分:0)

您是否尝试过Database属性?

GumpIndexDatabase.Database.Connection.ConnectionString = "your conn string";

我刚测试非常短,所以不能保证它没有问题。但我成功地在我的一个服务层类的构造函数中使用它:

public class MyService
{
    protected DataContext DataContext { get; set; }

    public MyService(DataContext dataContext)
    {
        DataContext = dataContext;
        DataContext.Database.Connection.ConnectionString = "conn string";
    }
}

看到DbContext过载DbContext(string nameOrConnectionString)。你也应该可以使用它。

使用现有连接

或者您使用现有连接。您的DbContext应该是这样的:

public class DataContext : DbContext
{
    public DataContext(DbConnection existingConnection)
        : base(existingConnection, true) { }
}

然后根据需要进行初始化:

public void SomeMethod()
{
    var connString = "whatever"; // could also be something like Textbox1.Text
    using (var connection = new SqlConnection(connString))
    {
        var context = new DataContext(connection);
    }
}

当然SqlConnection可以是从DbConnection继承的任何内容。请参阅DbConnection Class