如何以编程方式设置数据库文件名?

时间:2014-06-14 19:17:42

标签: c# entity-framework-6.1

关注this tutorial后,我创建了DbConfiguration课程:

class ImgSigDbConfig : DbConfiguration
{
    public ImgSigDbConfig()
    {
        SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0")); 
    }
}

告诉我的DbContext使用它:

[DbConfigurationType(typeof(ImgSigDbConfig))] 
class ImgSimContext : DbContext 
{

这似乎很好,但我不知道它在哪里存储我的数据,我不喜欢这样。我希望将所有内容保存到App_Data文件夹中的文件中。如何从ImgSigDbConfig构造函数中指定? (假设我对SQL服务器连接一无所知)


进行了更多挖掘并想出了这个:

public ImgSigDbConfig()
{
    var sqlConnBuilder = new SqlConnectionStringBuilder();
    sqlConnBuilder.DataSource = ".";
    sqlConnBuilder.InitialCatalog = "ImgSim.ImgSimContext";
    sqlConnBuilder.IntegratedSecurity = true;
    sqlConnBuilder.AttachDBFilename = @"App_Data\database.mdf";

    SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0", sqlConnBuilder.ToString()));
}

但现在它抛出:

  

提供程序未返回ProviderManifestToken字符串


根据haim和gunther的建议,我删除了多余的连接设置:

class ImgSigDbConfig : DbConfiguration
{
    public ImgSigDbConfig()
    {
        var sqlConnBuilder = new SqlConnectionStringBuilder();

        sqlConnBuilder.IntegratedSecurity = true;
        sqlConnBuilder.MultipleActiveResultSets = true;

        SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0", sqlConnBuilder.ToString()));
        SetManifestTokenResolver(new DefaultManifestTokenResolver());
    }
}

将它们移到Program.cs:

var conn = new SqlConnectionStringBuilder
{
    AttachDBFilename = @"App_Data\database.mdf",
    //InitialCatalog = "ImgSim.ImgSimContext",
};

using (var db = new ImgSimContext(conn.ToString()))

但即便如此,我得到一个带有InnerException的System.Data.Entity.Core.ProviderIncompatibleException

  

提供程序未返回ProviderManifestToken字符串。

即使我设置了SetManifestTokenResolver - 我想默认的一个不起作用?

4 个答案:

答案 0 :(得分:2)

LocalDbConnectionFactory构造函数v11.0允许连接到sqlserver 2012,默认情况下它尝试在app.config中查找连接字符串的名称作为上下文全名。假设您没有在config中指定连接字符串并且想要创建名为Test的数据库(在下面指定的数据目录中),那么您需要设置如下构造函数:

   [DbConfigurationType(typeof(ImgSigDbConfig))]
class MyDbContext : DbContext
{
    public MyDbContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
    }

    public DbSet<Person> Persons { get; set; }
}

现在你可以调用上下文:

AppDomain.CurrentDomain.SetData("DataDirectory", @"c:\App\DataDirectory");
        MyDbContext myDbContext = new MyDbContext("test"); //this is the name
        myDbContext.Persons.Add(new Person() { Id = 1, Name = "Name1" });
        myDbContext.SaveChanges();

配置将保持不变:

class ImgSigDbConfig : DbConfiguration
{
    public ImgSigDbConfig()
    {
        SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0"));
    }
}

请注意我手动设置datadirectory,因为它不是Web应用程序。您需要为此目录授予权限,以便可以创建和附加新数据库。 我的app.config是这样的:

    <configuration>  <configSections>    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />  </configSections>  <connectionStrings>
  </connectionStrings>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

答案 1 :(得分:1)

因此,默认情况下,Entity Framework将查找连接字符串以确定它应该打开哪个数据库,它当前使用的是SQL Expres的一个版本(请参阅here)。这只是默认设置,使您可以轻松开发。

典型的网站会有一个web.config文件,您可以找到。在那里你会看到类似的东西:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
          <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=testdb;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\testdb.mdf" providerName="System.Data.SqlClient" />
  </connectionStrings>

对于Windows窗体/控制台应用程序,将会出现app.config,但这些用途相同。

需要修改此连接字符串以使用您感兴趣的数据库,此时我建议connectionstrings.com。你可以指出SQL,Oracle或者你非常喜欢的任何东西。

答案 2 :(得分:1)

您可以根据提供给ImgSigContext的连接字符串创建数据库

示例:

public class ImgSigContext : DbContext{
   public ImgSigContext(string connectionString) : base(connectionString)
}

并使用

创建它
string connString = "..."; //here comes a valid connectionstring
bool created = new ImgSigContext(connString).Database.CreateIfNotExists();
//returns true if database didn't exist and is succesfully created
//works from Entity FrameWork 5 and up

或者像这样

// will automatically create if migrations is enabled
using(var context = new ImgSigContext(connString))
{
   // some logic comes here
}

答案 3 :(得分:1)

baseConnectionString构造函数上MyLocalDbConnectionFactory参数的文档明确指出:

  

用于除数据库以外的数据库选项的连接字符串   &#39; 初始目录&#39; <#39; 数据源&#39;以及&#39; AttachDbFilename &#39 ;.该   &#39;初始目录&#39;和&#39; AttachDbFilename&#39;将在此之前   调用CreateConnection时基于数据库名称的字符串。该   &#39;数据源&#39;将根据LocalDbVersion参数设置。

请改为尝试:

var sqlConnBuilder = new SqlConnectionStringBuilder();
sqlConnBuilder.IntegratedSecurity = true;
sqlConnBuilder.MultipleActiveResultSets = true;

如果您正在运行控制台应用程序,请确保实际设置了DataDirectory。使用:AppDomain.CurrentDomain.GetData("DataDirectory")