【问题标题】:Programmatically create DB from scratch in arbitrary location以编程方式在任意位置从头开始创建数据库
【发布时间】:2015-08-19 21:55:40
【问题描述】:

我正在开发一个使用 SQL Server Express/LocalDB 的简单桌面应用程序。我在任意非特权位置有一个数据目录,我想在那里创建一个数据库文件。我最初创建了数据库并生成了一个模型供 EF 使用;现在我想使用该模型在任何我想要的地方重新创建数据库。

我发现很多帖子都在做类似的事情,但他们似乎正在通过一个开始工作的上下文删除和重新创建现有数据库,以用于测试目的。我想从一个空目录开始。

使用here 中的代码提取我能够在磁盘上物理创建一个数据库文件,使用SQL 语句创建新的.mdf 和.ldf 文件。但是他们没有架构;如果我从 .mdf 文件启动上下文实例,然后尝试计算表中的行数,我会因为表不存在而引发异常。

如果我尝试调用ctx.Database.Create(),则会收到无法创建数据库的错误,因为它已经存在。当然可以,只是没有桌子。

如果我最初不使用原始 SQL 查询来创建新的空数据库,我尝试按如下方式创建上下文,其中 filespec 指向有效目录中不存在的 .mdf 文件,.mdf 文件。 Create() 总是抛出异常“无法创建数据库'',因为它已经存在”

string connectionString
        = "Data Source=(LocalDB)\\v11.0;AttachDbFilename="
        + fileSpec;

EventsListDBEntities ctx = new EventsListDBEntities();
ctx.Database.Connection.ConnectionString = connectionString;
ctx.Database.Create();
ctx.Database.Initialize(true);

如何让 EF 在我的空数据库中创建表,或从头开始创建文件?

【问题讨论】:

    标签: c# sql-server database entity-framework


    【解决方案1】:

    尝试改用以下方法:

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

    https://msdn.microsoft.com/en-us/library/system.data.entity.database.createifnotexists%28v=vs.113%29.aspx#M:System.Data.Entity.Database.CreateIfNotExists

    【讨论】:

    • Ta,但之前尝试过——因为在这两种情况下,它都认为数据库存在,CreateIfNotExists() 什么都不做,返回 false,尽管没有抛出异常,但只要我尝试计算在第二种情况下,我得到“基础提供程序在打开时失败”的行数,因为那里没有文件,而在第一种情况下,“对象不存在”或类似情况,因为数据库已打开但没有表。
    【解决方案2】:

    经过大量实验,这是我最终完成的代码。

    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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多