C# 以编程方式在任意位置从头开始创建DB
我正在开发一个使用SQLServerExpress/LocalDB的简单桌面应用程序。我在任意非特权位置有一个数据目录,我想在其中创建一个数据库文件。我最初创建了数据库并生成了一个供EF使用的模型;现在,我想使用该模型在任何需要的地方重新创建数据库 我发现很多帖子都做了类似的工作,但它们似乎是通过一个上下文删除和重新创建一个现有的数据库,这个上下文从一开始就在工作,用于测试目的。我想从一个空目录开始 使用中代码的摘录,我能够在磁盘上物理地创建一个数据库文件,使用SQL语句创建新的.mdf和.ldf文件。但是他们没有模式;如果我从.mdf文件启动一个上下文实例,然后尝试计算表中的行数,就会抛出一个异常,因为表不存在 如果我尝试调用C# 以编程方式在任意位置从头开始创建DB,c#,sql-server,database,entity-framework,C#,Sql Server,Database,Entity Framework,我正在开发一个使用SQLServerExpress/LocalDB的简单桌面应用程序。我在任意非特权位置有一个数据目录,我想在其中创建一个数据库文件。我最初创建了数据库并生成了一个供EF使用的模型;现在,我想使用该模型在任何需要的地方重新创建数据库 我发现很多帖子都做了类似的工作,但它们似乎是通过一个上下文删除和重新创建一个现有的数据库,这个上下文从一开始就在工作,用于测试目的。我想从一个空目录开始 使用中代码的摘录,我能够在磁盘上物理地创建一个数据库文件,使用SQL语句创建新的.mdf和.ld
ctx.Database.Create()
,则会得到一个错误,即无法创建数据库,因为它已经存在。当然有,只是没有桌子
如果我最初不使用原始SQL查询来创建新的空数据库,并且我尝试按如下方式创建上下文,并且filespec指向有效目录中不存在的.mdf文件,.create()始终引发异常“无法创建数据库“”,因为它已存在”
如何让EF在空数据库中创建表,或从头开始创建文件?尝试使用以下方法:
string connectionString
= "Data Source=(LocalDB)\\v11.0;AttachDbFilename="
+ fileSpec;
EventsListDBEntities ctx = new EventsListDBEntities();
ctx.Database.Connection.ConnectionString = connectionString;
ctx.Database.CreateIfNotExists(); // Change this line.
ctx.Database.Initialize(true);
经过大量的实验,下面是我最终使用的代码
string connectionString
= "Data Source=(LocalDB)\\v11.0;AttachDbFilename="
+ fileSpec + ";database=EventsListDB";
/* We can't go straight into the context and create the DB because
* it needs a connection to "master" and can't create it. Although this
* looks completely unrelated, under the hood it leaves behind something
* that EF can pick up and use- and it can't hurt to delete any references
* to databases of the same name that may be lurking in other previously
* used directories.
*/
SqlConnectionStringBuilder masterCSB = new SqlConnectionStringBuilder(connectionString);
masterCSB.InitialCatalog = "master";
masterCSB.AttachDBFilename = "";
using (var sqlConn = new SqlConnection(masterCSB.ToString()))
{
sqlConn.Open();
using (var cmd = sqlConn.CreateCommand())
{
bool done = false;
int attempt = 0;
do
{
try
{
cmd.CommandText =
String.Format(
"IF EXISTS (Select name from sys.databases " +
"WHERE name = '{0}') " +
"DROP DATABASE {0}", "EventsListDB");
cmd.ExecuteNonQuery();
done = true;
}
catch (System.Exception ex)
{
/* We sometimes get odd exceptions that're probably because LocalDB hasn't finished starting. */
if (attempt++ > 5)
{
throw ex;
}
else Thread.Sleep(100);
}
} while (!done);
}
}
/* Now we can create the context and use that to create the DB. Note that
* a custom constructor's been added to the context exposing the base
* constructor that can take a connection string- changing the connection
* string after the default constructor reads it from App.config isn't
* sufficient.
*/
EventsListDBEntities ctx = new EventsListDBEntities(connectionString);
ctx.Database.Create();
int numRecords = ctx.EventLists.Count(); //See if it really worked.
Ta,但之前尝试过,因为在这两种情况下它都认为DB存在,
CreateIfNotExists()
什么也不做,返回false,尽管没有抛出异常,但只要我尝试计算行数,就会在第二种情况下得到“底层提供程序打开失败”,因为没有文件,并且第一种情况下为“对象不存在”或类似,因为数据库已打开,但没有表。
string connectionString
= "Data Source=(LocalDB)\\v11.0;AttachDbFilename="
+ fileSpec + ";database=EventsListDB";
/* We can't go straight into the context and create the DB because
* it needs a connection to "master" and can't create it. Although this
* looks completely unrelated, under the hood it leaves behind something
* that EF can pick up and use- and it can't hurt to delete any references
* to databases of the same name that may be lurking in other previously
* used directories.
*/
SqlConnectionStringBuilder masterCSB = new SqlConnectionStringBuilder(connectionString);
masterCSB.InitialCatalog = "master";
masterCSB.AttachDBFilename = "";
using (var sqlConn = new SqlConnection(masterCSB.ToString()))
{
sqlConn.Open();
using (var cmd = sqlConn.CreateCommand())
{
bool done = false;
int attempt = 0;
do
{
try
{
cmd.CommandText =
String.Format(
"IF EXISTS (Select name from sys.databases " +
"WHERE name = '{0}') " +
"DROP DATABASE {0}", "EventsListDB");
cmd.ExecuteNonQuery();
done = true;
}
catch (System.Exception ex)
{
/* We sometimes get odd exceptions that're probably because LocalDB hasn't finished starting. */
if (attempt++ > 5)
{
throw ex;
}
else Thread.Sleep(100);
}
} while (!done);
}
}
/* Now we can create the context and use that to create the DB. Note that
* a custom constructor's been added to the context exposing the base
* constructor that can take a connection string- changing the connection
* string after the default constructor reads it from App.config isn't
* sufficient.
*/
EventsListDBEntities ctx = new EventsListDBEntities(connectionString);
ctx.Database.Create();
int numRecords = ctx.EventLists.Count(); //See if it really worked.