【问题标题】:How to set the right AttachDbFilename relative path in ASP.NET Core?如何在 ASP.NET Core 中设置正确的 AttachDbFilename 相对路径?
【发布时间】:2016-05-05 19:22:32
【问题描述】:

在基于 ASP.NET Core(前 ASP.NET 5)、.NET Core CLR RC1、EF Core(前 EF 7)、启用 EF 迁移、LocalDb v11.0 的 Web 项目上使用 VS2015。

我手动(通过SQL命令)创建了一个数据库,并将MDF/LDF文件放在了项目子目录下,情况类似:

MySolution\src\MyProject\MyLocalData\
  - MyLocalDb.mdf
  - MyLocalDb_log.ldf

这是appsettings.json 中设置的"ConnectionString" 键的值(或者至少是我尝试过的众多之一):

"Data Source=(LocalDb)\\v11.0;AttachDbFilename=.\\MyLocalData\\MyLocalDb.mdf;Integrated Security=True"

初始迁移已正确创建,现在我卡在dnx ef database update 命令(请参阅official tutorial),出现此错误:

错误号:15350,状态:1,类:14 尝试为文件 .\MyLocalData\MyLocalDb.mdf 附加自动命名数据库失败。存在同名数据库,或指定文件无法打开,或位于 UNC 共享上。

我很确定没有其他具有该名称的数据库,在我的用户主目录中检查了文件,并在 Sql Server Management Studio 中检查了 LocalDb 实例中的数据库。事实上,如果我切换到AttachDbFilename 中的绝对文件路径,迁移会进一步移动(并发现与通过 EF fluent 接口设置的列属性相关的其他错误,但这是另一回事)。

所以在我看来,这完全是在AttachDbFilename 中找到正确的relative 路径。我在 SO 上搜索了相关主题,但找不到任何答案。我还尝试更改相对路径,假设 current 文件夹是 wwwrootartifacts 文件夹,但没有运气。

有人知道如何正确设置吗?助教

【问题讨论】:

    标签: c# entity-framework asp.net-core


    【解决方案1】:

    我现在有这项工作,而且工作很辛苦。 关键是环境信息“ContentRootPath”,在您的示例中将返回 MySolution\src\MyProject

    的路径

    我的测试应用是下面的“数据库优先”教程 https://docs.efproject.net/en/latest/platforms/aspnetcore/existing-db.html

    进行了一些更改,以适应我教授网络应用程序编程的情况,并需要我和学生可以在彼此的机器上运行以进行讨论、标记等的自包含应用程序。

    在 appsettings.json 中

        {
      "ConnectionStrings": {
        "DefaultConnection": "Server=(localdb)\\mssqllocaldb;AttachDBFilename=%CONTENTROOTPATH%\\App_Data\\blogging.mdf;Trusted_Connection=true;MultipleActiveResultSets=true"
      }
    

    与众不同的部分是:

    AttachDBFilename=%CONTENTROOTPATH%\\App_Data\\blogging.mdf
    

    好的,我使用的是传统名称“App_Data”,但它在 ContentRootPath 下比在“wwwroot”下更安全。

    然后在 Startup.cs 中

    public class Startup
    {
        //20160718 JPC enable portable dev database
        private string _contentRootPath = "";
    
        public Startup(IHostingEnvironment env)
        {
            //20160718 JPC enable portable dev database
            _contentRootPath = env.ContentRootPath;
        ...
        }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //20160718 JPC enable portable dev database
            string conn = Configuration.GetConnectionString("DefaultConnection");
            if(conn.Contains("%CONTENTROOTPATH%"))
            {
                conn = conn.Replace("%CONTENTROOTPATH%", _contentRootPath);
            }
            ...
         }
    

    上面的“...”代表Visual Studio 2015生成的标准代码。

    请注意,当我们“发布”这样的应用程序时,我们需要手动将自定义文件夹和文件(例如我的“App_Data”文件夹)复制并粘贴到发布的版本中。或者我们可以将自定义文件夹名称(在本例中为“App_Data”)添加到文件“project.json”中。

    还很高兴知道,对于包括控制器类在内的任何类,我们都可以添加一个带参数 env 的构造函数方法,并且托管环境将为我们提供有用的信息,包括 ContentRootPath。用于自定义文件存储,例如为我们的用户提供文件上传。

    public class HomeController : Controller
    {
        //20160719 JPC access hosting environment via controller constructors
        private IHostingEnvironment _env;
    
        public HomeController(IHostingEnvironment env)
        {
            _env = env;
        }
    
        public IActionResult Index()
        {
            string contentRootPath = _env.ContentRootPath;
            return View();
        }
    

    好的,这只是为了演示原理,因为我在“return View()”上添加了一个断点,然后将鼠标悬停在 contentRootPath 上以说明这一点。

    ASP.NET Core MVC6 看起来像是我遇到的更大的学习和教学挑战之一。祝我们所有人好运。我发现了一个不错的进步:在 MVC5 中,我们有一些戏剧性的事情,让我们的自定义数据和身份 AspNetUser 表在一个数据库中很好地结合在一起。看起来它在 MVC6 中是一个更整洁的命题。

    【讨论】:

    • 感谢您的详尽回答。从那以后,我放弃了将开发数据库文件放在项目本地的想法,并转向在堆栈决定的任何地方(我的用户文件夹)创建它们的“标准”案例。无论如何,我们都在处理迁移(以及developmnet 中的数据种子),因此我们可以轻松地从头开始重新创建相同的数据库和数据。
    • 旁注:我没有在实践中尝试过,但自从 1.0 RTM project.json 提供了一个带有嵌套 include 字段的 publishOptions 字段,您可以在其中列出文件的相对路径/glob以及发布时应考虑的文件夹。也许试试"publishOptions": { "include": [ "App_Data", "wwwroot", "Views", "appsettings.json", "web.config" ] }
    • 感谢@superjos 的“旁注:”我现在已经尝试过了(将自定义文件夹添加到project.json),这是有效的。我已经更新了帖子。部署到网络服务器已经有效,但不适用于 localdb - 我必须使用传统的 SQL Server 并附加数据库。部署的主要发现是在安装 ASP.NET Core 1.0 网络服务器包后需要完全重启网络服务器。
    • 我猜可能没有安装 SqlServer LocalDb 或者无论如何不能在服务器上运行,我会说有充分的理由。当然要根据实际使用情况,你的场景看起来很有教育意义,但至少你应该使用 Sql Server Express。
    • IHostingEnvironment 现在在 .NET Core 3.1 中已弃用,最好用 IWebHostEnvironment 替换
    【解决方案2】:

    我找到了一个更简单的方法

    1. 运行您的应用并在默认位置创建数据库

    2. 打开 Microsoft Sql Server Management Studio(或者您更喜欢 IDE)并创建一个新连接以指向 (localdb)\mssqllocaldb

    3. 将数据库脚本作为 CREATE

    4. 更改文件名中的路径

    5. 删除您在步骤 1 中创建的数据库(选择关闭现有连接)

    6. 运行脚本

    您的应用程序应该可以在不更改配置中的任何内容的情况下运行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      相关资源
      最近更新 更多