How to programatically set database filename?

随声附和 提交于 2019-12-06 14:52:52

问题


Following this tutorial, I've created my DbConfiguration class:

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

And told my DbContext to use it:

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

Which seems to connect fine, but I have no idea where it's storing my data, and I don't like that. I would like it to save everything to a file in the App_Data folder. How can I specify that from inside my ImgSigDbConfig constructor? (Assume I know nothing about SQL server connections)


Did some more digging and came up with this:

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()));
}

But now it throws:

The provider did not return a ProviderManifestToken string


Per haim and gunther's suggestions I removed the superfluous connection settings:

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());
    }
}

And moved them into Program.cs:

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

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

But even so, I get a System.Data.Entity.Core.ProviderIncompatibleException with InnerException:

The provider did not return a ProviderManifestToken string.

Even though I set a SetManifestTokenResolver -- I guess the default one doesn't work??


回答1:


LocalDbConnectionFactory constructor v11.0 allows to connect to sqlserver 2012 and by default it tries to find the name of the connection string in app.config as context full name. Say you have not specified the connection string in config and want to create a database named Test ( In a datadirectory specified below) then you need to set the constructor like this:

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

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

Now you can call the context :

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();

The configuration will remain same:

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

Watch that I am setting the datadirectory manually as it is not a web app. You need to give permissions to this directory so that a new database can be created and attached. My app.config is like this:

    <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>



回答2:


So by default Entity Framework will look for a connection string to determine which database it should open, the current one it's using is a a version of SQL Expres (see here). This is just the default setup making development easy for you.

A typical website will have a web.config file that you can find. In there you'd expect to see something like:

<?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>

For a windows forms/console application there will be an app.config instead, these serve the same purpose however.

This connection string needs to be modified to use the database you're interested in, at this point I'd recommend connectionstrings.com. You can make it point at SQL, Oracle or whatever you like pretty much.




回答3:


You can create a database based on a connectionstring you give to your ImgSigContext

example:

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

and create it by using

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

or like this

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



回答4:


The documentation of the baseConnectionString parameter on MyLocalDbConnectionFactory constructor explicitly states that:

The connection string to use for options to the database other than the 'Initial Catalog', 'Data Source', and 'AttachDbFilename'. The 'Initial Catalog' and 'AttachDbFilename' will be prepended to this string based on the database name when CreateConnection is called. The 'Data Source' will be set based on the LocalDbVersion argument.

Try this instead:

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

If you're running a Console Application make sure your DataDirectory is actually set. Use: AppDomain.CurrentDomain.GetData("DataDirectory").



来源:https://stackoverflow.com/questions/24223396/how-to-programatically-set-database-filename

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!