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