如何让用户首先在C#EF4.1代码中动态指定数据库提供程序和连接详细信息?

如何让用户首先在C#EF4.1代码中动态指定数据库提供程序和连接详细信息?,c#,database,ef-code-first,connection-string,C#,Database,Ef Code First,Connection String,我正在创建一个C#应用程序,以替换使用MySQL数据库的VB6应用程序,其中应用程序的多个副本使用同一数据库。新的应用程序必须能够使用当前的MySQL数据库,但我也希望它与数据库无关,这样应用程序的未来实例可以使用用户想要的任何服务器。在一个完美的世界中,我希望第一次运行的应用程序为用户提供一个对话框,让他们选择数据库类型(MySQL、SQL Server等),并指定服务器ip、用户、密码和数据库名称。然后,应用程序将连接到该服务器,如果数据库已经存在,则使用该数据库;如果数据库不存在,则创建一

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

首先使用代码,我已经了解了如何使用现有数据库或创建新数据库,但只能通过硬编码App.config文件中的连接字符串

    <add name="GumpIndexDatabase"
     connectionString="server=localhost;userid=123;password=123;port=3306;database=gump_new_data;pooling=false;"
     providerName="MySql.Data.MySqlClient"
     />
几个小时的搜索还没有找到一个例子来说明如何做这样的事情,所以我怀疑这是不允许或不推荐的,尽管这看起来很简单。我看过一些关于连接字符串生成器的文章,但不了解如何从通用对象获取特定于数据库的字符串


因此,一个简单的问题是:如何在运行时指定数据库连接详细信息?

您是否尝试了
数据库
属性

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(字符串名称或连接字符串)
。你也应该能用这个

使用现有连接 或者使用现有连接。您的
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
继承的任何东西。请参阅。

我不建议强制执行此功能,除非你100%肯定没有它你就活不下去。它增加了许多维护任务,而这些任务目前可能并不明显(例如更新到新版本、修复bug、花费大量时间找出通用接口、维护这些接口、进行大量测试等等)。因此,除非它是一个被要求的业务特性,否则就不要管它了

然而,如果您知道自己在做什么,这个问题通常是通过接口解决的。可能存在这些通用接口(itslef的任务是找出它们):

  • i连接
  • IDataProvider
  • i假设
目前,您将使用MySql数据库实现接口,例如
classmysqlconnection:IConnection
。如果需要MS SQL,
类MSSQLSconnection:IConnection


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

是的,如果我已经有字符串,我可以这样做来设置字符串,但是如何在不硬编码不同版本的情况下创建一个?另外,我还需要更换供应商。哇,听起来非常复杂。由于我的应用程序只需要知道它使用的服务器是app.config文件,所以很难相信动态地做到这一点。我所有的查询都是简单的Linq,所以如果我使用MySQL或MSSQL,应用程序中不会有任何变化。谢谢你提供的信息。@Matt我明白你的意思,我做了几个项目。问题在于LINQ,在某种程度上,就在它被发送到服务器之前,它必须转换成SQL(MSSQL T-SQL或MySQL SQL,不管它是什么)。所以在某个时刻,LINQ必须知道它连接到哪个数据库。它们都是相互竞争的,因此没有一种通用的SQL语言可以被所有的数据库支持。因此,每个数据库的提供程序必须不同。您可能可以搜索:
generic repository c#sample
,您应该能够找到两个好的示例。也许我需要重新措辞-我知道提供者必须不同,这就是为什么我想让用户选择它。然后,该选择将决定创建什么类型的数据库对象,并负责将我的Linq查询转换为特定于Db的查询。可能我只是遗漏了一些东西,但似乎很简单。将LINQ转换成SQL是一项困难的任务。开发和测试单个供应商可能需要很多人年的时间。我很想知道是否有一种更简单的做事方式。但对你来说这并不重要,因为你只需要使用现有的提供者。在这种情况下,您需要实现的是接口和实现方面的抽象,在tern中称之为事实提供者,如(EF、NHibernate、ADO.NET等),我将其标记为正确答案,尽管它或多或少表示“您不能这样做!”谢谢
public void SomeMethod()
{
    var connString = "whatever"; // could also be something like Textbox1.Text
    using (var connection = new SqlConnection(connString))
    {
        var context = new DataContext(connection);
    }
}