【问题标题】:"URI formats are not supported" exception when using |DataDirectory| in Entity Framework connection string使用 |DataDirectory| 时出现“不支持 URI 格式”异常在实体框架连接字符串中
【发布时间】:2012-09-24 10:46:32
【问题描述】:

我在 Visual Studio 2012 中有一个单元测试项目,我在其中存储 SQL Server 2012 的 AdventureWorks MDF 文件(该文件名为 AdventureWorks2012_Data.mdf)。在 Visual Studio Server Explorer 中,我可以在数据连接中添加 MDF 并浏览数据库。右键单击 $/Data Connections/AsventureWorks2012_Data.mdf 并选择属性使我可以访问连接字符串,如下所示:

Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Projects\Common\Source\Framework\Framework.Data.Tests\AdventureWorks2012_Data.mdf;Integrated Security=True;Connect Timeout=30

我将其复制到 app.config 文件中的实体框架连接字符串中,如下所示:

<!-- Works :-) -->
<connectionStrings>
  <add name="AdventureWorksEntities" 
       connectionString="metadata=res://*/Repository2Tests.AdventureWorks.csdl|res://*/Repository2Tests.AdventureWorks.ssdl|res://*/Repository2Tests.AdventureWorks.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Projects\Common\Source\Framework\Framework.Data.Tests\AdventureWorks2012_Data.mdf;Integrated Security=True;Connect Timeout=30App=EntityFramework&quot;" 
       providerName="System.Data.EntityClient" />
</connectionStrings>

请注意,AttachDbFilename 包含 MDF 文件的完整路径: C:\Projects\Common\Source\Framework\Framework.Data.Tests\AdventureWorks2012_Data.mdf

当我运行单元测试时,一切正常。

我按照“ADO.NET Entity Framework Connection Strings”中的描述将 AttachDbFilename 更改为 |DataDirectory|\AdventureWorks2012_Data.mdf,并按照“ADO.NET |DataDirectory| where is this documented?”中的描述设置 DataDirectory,这样我的连接字符串现在如下所示:

<!-- Doesn't work :-( -->
<connectionStrings>
  <add name="AdventureWorksEntities" 
       connectionString="metadata=res://*/Repository2Tests.AdventureWorks.csdl|res://*/Repository2Tests.AdventureWorks.ssdl|res://*/Repository2Tests.AdventureWorks.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\AdventureWorks2012_Data.mdf;Integrated Security=True;Connect Timeout=30;App=EntityFramework&quot;" 
       providerName="System.Data.EntityClient" />
</connectionStrings>

使用 |DataDirectory| 的变化导致以下运行时错误:

System.Data.EntityException: The underlying provider failed on ConnectionString. ---> System.ArgumentException: URI formats are not supported.
HResult: -2147024809
at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength)
at System.IO.Path.GetFullPath(String path)
at System.Data.Common.ADP.GetFullPath(String filename)
at System.Data.Common.DbConnectionOptions.ExpandDataDirectory(String keyword, String value, String& datadir)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous)
at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions)
at System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key)
at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
at System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString)
--- End of inner exception stack trace ---
HResult: -2146233087
at System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString)
at System.Data.Entity.Internal.LazyInternalConnection.TryInitializeFromAppConfig(String name, ConnectionStringSettingsCollection connectionStrings)
at System.Data.Entity.Internal.LazyInternalConnection.Initialize()
at System.Data.Entity.Internal.LazyInternalConnection.get_ConnectionHasModel()
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.Create()

我已经对此进行了几天的研究,并尝试了无数种变化,但均未成功。我什至调试了 Microsoft 代码,但通过编译器优化,我无法在堆栈上看到任何调试信息。

有人遇到过这个具体问题吗?

【问题讨论】:

    标签: entity-framework connection-string datadirectory


    【解决方案1】:

    当我开始向 Microsoft 提交错误报告并着手复制步骤时,我终于解决了这个问题。

    长话短说,问题出在设置 DataDirectory 的代码中:

    AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory);
    

    问题是我的 dataDirectory 变量被初始化为 file://C:/myfolder/etc/ 而不是 C:\myfolder\etc\。我更正了负责该问题的代码,问题得到解决。顺便说一下,我使用的代码是:

    // in the test assembly initializer
    String dataDirectory = AppDomain.CurrentDomain.GetApplicationPath();
    AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory);
    
    // GetApplicationPath calls into the following extension method
    /// <summary>
    /// Defines a set of extension methods on <see cref="AppDomain"/> objects.
    /// </summary>
    public static class AppDomainExtensions
    {
        /// <summary>
        /// Gets the application path (works for both ASP.NET and unit tests).
        /// </summary>
        /// <returns></returns>
        public static string GetApplicationPath(this AppDomain appDomain)
        {
            string binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            return binPath.Substring(0, binPath.LastIndexOf("bin", StringComparison.InvariantCultureIgnoreCase));
        }
    }
    

    【讨论】:

    • 一个小提示,如果项目的输出目录是“Build”而不是“bin”,这可能会失败。尽管如此,一个很好的解决方案!
    • 我在我的一个项目中遇到了同样的问题,其中原始程序员使用了 GetExecutingAssembly().GetName().Codebase。切换到 GetExecutingAssembly().Location 解决了此处提供的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    相关资源
    最近更新 更多