MetadataException:无法加载指定的元数据资源

Posted

技术标签:

【中文标题】MetadataException:无法加载指定的元数据资源【英文标题】:MetadataException: Unable to load the specified metadata resource 【发布时间】:2010-10-15 22:01:58 【问题描述】:

突然间,我在实例化生成的ObjectContext 类时不断收到MetadataException。 App.Config 中的连接字符串看起来是正确的 - 自上次工作以来没有改变 - 我已经尝试从底层数据库重新生成一个新模型(edmx 文件),没有任何变化。

有人有什么想法吗?

更多细节:我没有更改任何属性,我没有更改任何输出程序集的名称,我没有尝试在程序集中嵌入 EDMX。我从下班到回来只等了10个小时。然后它就不再工作了。

我已尝试重新创建 EDMX。我已经尝试重新创建该项目。我什至尝试从头开始重新创建数据库。无论如何都没有运气。

【问题讨论】:

如果某个特定产品的浏览量超过 20 万次的问题 SO,那么该产品没有按照用户期望的方式运行。我希望看到微软解决这个问题。如果您有时间,可以通过以下链接向他们提供建议:visualstudio.uservoice.com/forums/121579-visual-studio。 我的问题解决了,通过替换从 db-layer 项目复制的连接字符串。 我也面临这个问题,我只是清理并重建解决方案,效果很好。 萨德侯爵还健在,在微软工作。这真的是实体框架的地狱。 【参考方案1】:

这意味着应用程序无法加载 EDMX。有几件事会导致这种情况。

您可能已将模型的 MetadataArtifactProcessing 属性更改为复制到输出目录。 连接字符串可能有误。我知道您说您没有更改它,但如果您更改了其他内容(例如,程序集的名称),它仍然可能是错误的。 您可能正在使用后编译任务将 EDMX 嵌入到程序集中,但由于某种原因它不再工作。

简而言之,您的问题中没有足够的细节来给出准确的答案,但希望这些想法能让您走上正轨。

更新:我写了a blog post with more complete steps for troubleshooting。

【讨论】:

连接字符串,尽管我上次努力将其与内容比较实用程序进行比较,但 是错误的。 这也是我的连接字符串。当您的集成测试也需要在其自己的 App.config 中进行连接时,当您更新 edmx 时,事情可能会不同步。 好的,我通过简单地设置“嵌入”来修复它;编译,然后将其重置为另一个。这解决了我的问题。 如果它是连接字符串,并且您正在执行“DB first”,您可以通过比较在 edmx 设计器中“从数据库更新”时获得的内容来轻松判断(在大多数情况下)您的 web.config 或 app.config 中有什么。 很棒的指南。对我来说,当我真的想要 res://*/MyModel1... 时,我复制了另一个使用 res://*/Database.MyModel2... 的连接字符串(数据库是我的集成测试项目中的一个文件夹) 【参考方案2】:

最终的解决方案(即使在另外两台机器上重新创建数据库,以及 EDMX 和其他杂项)是不使用实体框架的第一版。期待在 .NET 4.0 中再次对其进行评估。

在遇到同样的问题再次并到处寻找答案后,我终于找到了遇到同样问题的人。似乎 Visual Studio 的向导没有正确生成连接字符串,并且元数据资源的链接缺少重要路径。

v1.0 BUG?: Unable to load the specified metadata resource. Scripts != Models

2013 年 1 月 16 日更新:已经过渡到几乎完全使用 EF 代码优先实践(即使使用现有数据库),这个问题不再是问题。对我来说,这是一个可行的解决方案,可以减少自动生成的代码和配置造成的混乱,并增加我对产品的控制。

【讨论】:

【参考方案3】:

这个小改动有助于解决这个问题。

我有 3 个项目的解决方案。

connectionString="metadata=res://*/Model.Project.csdl|res://*/Model.Project.ssdl|res://*/Model.Project.msl;

改成

connectionString="metadata=res://*/;

【讨论】:

它为我修好了,但这到底是什么意思? @Lance:我在this blog post中详细解释了这一点 @jocull:不,它在很多情况下不起作用,在其他情况下会很慢。阅读我的博文以了解原因。 已将我的 .edmx 移至模型文件夹并忘记更新连接字符串。伟大的指针。谢谢。我需要几个小时才能弄清楚。 我已经完成了,我解决了一个问题,但给了我另一个All artifacts loaded into an ItemCollection must have the same version. Multiple versions were encountered. - 最后是 Npgsql。只有完整路径解决了这两个问题。【参考方案4】:

我遇到了同样的问题。我用反射器查看了我编译的 dll,发现资源的名称不正确。我重命名了,现在看起来很好。

【讨论】:

【参考方案5】:

我遇到了类似的错误。我重新创建了这个项目(长篇大论),并从旧项目中提取了所有内容。我之前没有意识到我的模型在一个名为“Model”的目录中,现在在一个名为“Models”的目录中。一旦我从这里更改了我的 Web.Config 中的连接:

<add name="RecipeManagerEntities" connectionString="metadata=res://*/Model.Recipe.csdl 

到这里:

<add name="RecipeManagerEntities" connectionString="metadata=res://*/Models.Recipe.csdl

一切正常(将Model 更改为Models)。请注意,我必须更改此字符串中的这三个位置。

【讨论】:

我将我的实体框架模型从模型移到了 DAL。但是后来当我在测试项目中写了一个测试(一周后)来测试Linq predicatebuilder。我得到了这个错误。我用它在主项目的 web.config 中的外观更正了测试项目 App.config - 正如你在三个地方所说的那样。所以你的简单回答让我走上了正轨。 这两者有区别吗?! @ErwinRooijakkers Model vs ModelS 在阅读 Craig 的博客后发现我也做了同样的事情,但是 +1 学习重要的是要记住,在“实体”类库中所做的更改不是在配置文件中自动进行的引用它的项目。 /sigh 很高兴我并不孤单。【参考方案6】:

当我不小心将 edmx 文件的构建操作(出现在 IDE 中的属性下)从“EntityDeploy”切换到“None”时,这发生在我身上。 EntityDeploy 为您填充元数据:请参阅http://msdn.microsoft.com/en-us/library/cc982037.aspx

【讨论】:

这是我的修复 - 我将我的 edmx 重命名为 .old,因为我复制了它并尝试了一些东西,之后当我将它重命名为 Build Action 时,将其自身设置为 none,因此得到了这个错误,将其设置回 EntityDeploy 解决了我的问题:) 我已将我的 EDMX 文件移动到另一个文件夹,并且必须更改构建操作以更新嵌入的资源名称。谢谢! 这是我的解决方案;在升级到 .NET Standard 的过程中,我丢失了该设置。谢谢你拯救了我的理智! 这也是我的修复。必须设置与旧项目相同的 edmx 文件属性设置:EntityDeploy / Do not copy / EntityModelCodeGenerator【参考方案7】:

我刚刚度过了愉快的 30 分钟。我重命名了实体对象,重命名了配置文件中的条目,但还有更多......你还必须更改对 csdl 的引用

很容易错过 - 如果您要重命名,请确保获得所有内容 ....

【讨论】:

【参考方案8】:

我也遇到了与 Rick 相同的问题和解决方案,除了我将现有的 .edmx 导入到新项目中,虽然基本命名空间无关紧要,但它被导入到不同的子目录中,所以我还必须在三个位置更新 Web.Config 中的连接字符串,以包含不同的子目录命名:

【讨论】:

【参考方案9】:

我的理论是,如果您有多个同名的 edmx 文件(例如 Model1),它将给出该异常。 当我决定将所有 edmx 文件(位于不同项目中)命名为 Model1 时,我遇到了同样的问题,因为我认为它们应该是独立的。

【讨论】:

【参考方案10】:

当 Edmx 在一个项目中并且您在另一个项目中使用它时,您可能会遇到此异常。

原因是Res://*/ 是一个指向当前程序集中资源的uri。如果 Edm 是在与使用它的代码不同的程序集中定义的,则 res://*/ 将无法工作,因为找不到资源。

您需要提供程序集的全名(包括公钥令牌),而不是指定“*”。例如:

res://YourDataAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdefabcedf/YourEdmxFileName.csdl|res://...

构造连接字符串的更好方法是使用 EntityConnectionStringBuilder:

public static string GetSqlCeConnectionString(string fileName)

    var csBuilder = new EntityConnectionStringBuilder();

    csBuilder.Provider = "System.Data.SqlServerCe.3.5";
    csBuilder.ProviderConnectionString = string.Format("Data Source=0;", fileName);

    csBuilder.Metadata = string.Format("res://0/YourEdmxFileName.csdl|res://0/YourEdmxFileName.ssdl|res://0/YourEdmxFileName.msl", 
        typeof(YourObjectContextType).Assembly.FullName);

    return csBuilder.ToString();


public static string GetSqlConnectionString(string serverName, string databaseName)

    SqlConnectionStringBuilder providerCs = new SqlConnectionStringBuilder();

    providerCs.DataSource = serverName;
    providerCs.InitialCatalog = databaseName;
    providerCs.IntegratedSecurity = true;

    var csBuilder = new EntityConnectionStringBuilder();

    csBuilder.Provider = "System.Data.SqlClient";
    csBuilder.ProviderConnectionString = providerCs.ToString();

    csBuilder.Metadata = string.Format("res://0/YourEdmxFileName.csdl|res://0/YourEdmxFileName.ssdl|res://0/YourEdmxFileName.msl",
        typeof(YourObjectContextType).Assembly.FullName);

    return csBuilder.ToString();

如果您仍然遇到异常,请在反射器中打开程序集并检查 .csdl、.ssdl 和 .msl 文件的文件名。当资源的名称与元数据值中指定的名称不同时,它将不起作用。

【讨论】:

请考虑“YourEdmxFileName”必须是限定名称,例如“YourNamespace.YourEdmxFileName”,如果您在程序集中使用命名空间。但是,您必须删除名称空间中与程序集名称相同的部分。 MSDN says the second paragraph is wrong. "当您使用通配符 (*) 时,实体框架必须在所有程序集中查找具有正确名称的资源。" 我很确定命名空间不相关,但嵌入的文件路径是。因此,即使您检查关联 edmx 文件的 *.Designer.cs 文件并注意到自动生成的类命名空间是 MyCompany ......无论如何,这不是您应该使用的。相反,路径是程序集名称、解决方案文件夹名称/文件名。例如:“metadata=res://*/EntityModels..csdl|” + "res://*/EntityModels..ssdl|" + "res://*/EntityModels..msl;" @Daniel,这基本上是正确的,但请注意命名空间和嵌入的文件路径有时是相同的。您必须查看 Reflector(或免费的替代品)才能确定。 它看起来只使用程序集名称,没有版本,publickeytoken等。喜欢:res://MyAssembly/folder.&lt;filename&gt;.csdl...【参考方案11】:

就我而言,此问题与重命名模型的 edmx 文件有关...更正 csdl/ssdl/msl 文件的 app.config 连接字符串解决了我的问题。

如果您使用 EF 4.0 设计器生成 csdl/ssdl/msl,这 3 个“文件”实际上将存储在模型的主 edmx 文件中。在这种情况下,Waqas 的帖子非常符合要求。重要的是要理解他的示例中的“Model_Name”需要更改为模型的 .edmx 文件的当前名称(没有 .edmx)。

另外,如果您的 edmx 文件不在项目的根级别,您需要在 Model_Name 前面加上相对路径,例如

res://*/MyModel.WidgetModel.csdl|res://*/MyModel.WidgetModel.ssdl|res://*/MyModel.WidgetModel.msl

将指定 csdl/ssdl/msl xml 存储在模型文件“WidgetModel.edmx”中,该文件存储在名为“MyModel”的文件夹中。

【讨论】:

【参考方案12】:

当 ObjectContext 对象在与使用它的项目不同的项目中定义时,我编写了这个帮助类来创建 ObjectContext 对象的实例。我解析配置文件中的连接字符串并用完整的程序集名称替换'*'。

它并不完美,因为它使用反射来构建对象,但它是我能找到的最通用的方法。

希望对某人有所帮助。

public static class EntityHelper<T> where T : ObjectContext

    public static T CreateInstance()
    
        // get the connection string from config file
        string connectionString = ConfigurationManager.ConnectionStrings[typeof(T).Name].ConnectionString;

        // parse the connection string
        var csBuilder = new EntityConnectionStringBuilder(connectionString);

        // replace * by the full name of the containing assembly
        csBuilder.Metadata = csBuilder.Metadata.Replace(
            "res://*/",
            string.Format("res://0/", typeof(T).Assembly.FullName));

        // return the object
        return Activator.CreateInstance(typeof(T), csBuilder.ToString()) as T;
    

【讨论】:

【参考方案13】:

对于你们所有人SelftrackingEntities用户, 如果您已遵循 Microsoft 演练并将 Object 上下文类分为 wcf 服务项目(通过链接到上下文.tt)所以这个答案是给你的:

这篇文章中显示的部分答案包括如下代码:

... = string.Format("res://0/YourEdmxFileName.csdl|res://0/YourEdmxFileName.ssdl|res://0/YourEdmxFileName.msl", 
        typeof(YourObjectContextType).Assembly.FullName); 

不会为您工作!原因是 YourObjectContextType.Assembly 现在驻留在不同的 Assembley 中(在 wcf 项目程序集中),

所以你应该用 -->

替换 YourObjectContextType.Assembly.FullName
ClassTypeThatResidesInEdmProject.Assembly.FullName 

玩得开心。

【讨论】:

【参考方案14】:

我能够在 Visual Studio 2010 VB.net (ASP.NET) 4.0 中解决此问题。

在实体模型向导期间,您将能够看到实体连接字符串。从那里您可以复制并粘贴到您的连接字符串中。

我唯一缺少的是“App_Code”。在连接字符串中。

entityBuilder.Metadata = "res://*/App_Code.Model.csdl|res://*/App_Code.Model.ssdl|res://*/App_Code.Model.msl"

【讨论】:

很遗憾,向导中的连接字符串对于 app.config 不正确。 @leqid 提出了修复模型路径的好方法。【参考方案15】:

此异常的另一个原因是您在 ObjectQuery 中包含相关表,但输入了错误的导航属性名称。

例子:

var query = (from x in myDbObjectContext.Table1.Include("FKTableSpelledWrong") select x);

【讨论】:

【参考方案16】:

对于我来说,它是通过更改 edmx 文件的属性来解决的。

    打开 edmx 文件 右键单击 EDMX 设计器的任意位置 选择属性 将名为“元数据工件处理”的属性更新为“嵌入输出程序集”

这解决了我的问题。 问题是,当容器试图找到元数据时,它找不到它。所以只需在同一个程序集中进行即可。 如果您的 edmx 文件在另一个程序集中,此解决方案将不起作用

【讨论】:

+1,000,000 这是我今天的根本问题。重组产品命名空间和整合程序集的痛苦。【参考方案17】:

我遇到了同样的错误消息。我的问题已通过关闭并重新打开 Visual Studio 2010 得到解决。

【讨论】:

【参考方案18】:

有时不加载包含模型的程序集:

    [TestMethod]
    public void TestOpenWithConfigurationAfterExplicit()
    
        String dummy = typeof(MallApp).Assembly.FullName;  
        //force the assembly loaded.
        using (DbContext ctx = new DbContext("name=MyContainer))
        
        
    

MallApp 类型与实体模型位于同一程序集中。如果没有显式加载,将抛出 System.Data.MetadataException

【讨论】:

【参考方案19】:

我在解决方案文件夹中包含项目的解决方案中遇到了同样的问题,当它们被移动到解决方案根目录时(为了克服由于项目位置而导致的 Mvc3AppConverter 的可疑错误)。

虽然根据需要重新添加了所有*项目引用后编译的解决方案,但在网站启动时抛出了错误。

EDMX 位于已移动的项目之一(“数据”项目)中,但当然,缺少对数据项目的引用不会导致编译错误,只是运行时错误。

只需添加对主项目的缺失引用即可解决此问题,根本无需编辑连接。

我希望这对其他人有帮助。

【讨论】:

【参考方案20】:

因为我重命名了一个程序集,所以遇到了同样的问题。

我还必须在项目 Properties/AssemblyInfo.cs 中的 AssemblyTitle 和 AssemblyProduct 属性中重命名它,并删除并重新添加对 edmx 文件的引用。

然后它工作得很好。

【讨论】:

【参考方案21】:

就我而言,我已经分离了数据访问层和用户界面层。 所以我每层都有实体连接字符串。

在我将这两个分开的连接字符串修改为相同之前,我仍然发现下面的错误。

Unable to load the specified metadata resource

所以我为这两层(DAL、UI)设置了相同的连接字符串,它工作得很好。

我的解决方案是让所有连接字符串都相同,无论它们已经出现在哪里

【讨论】:

【参考方案22】:

我也遇到了这个问题,这是因为我的 web.config 中的连接字符串与我的 EDMX 所在程序集的 app.config 中的连接字符串略有不同。不知道为什么会改变,但这里有两个不同的版本。

App.config:

<add name="SCMSEntities" connectionString="metadata=res://*/Model.SMCSModel.csdl|res://*/Model.SMCSModel.ssdl|res://*/Model.SMCSModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=SANDIEGO\sql2008;initial catalog=SCMS;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />

Web.config:

<add name="SCMSEntities" connectionString="metadata=res://*/Model.SCMSModel.csdl|res://*/Model.SCMSModel.ssdl|res://*/Model.SCMSModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=SANDIEGO\sql2008;initial catalog=SCMS;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

修复它的方法是简单地将 app.config 字符串复制到 web.config 中(注意末尾的细微差别 - 而不是“App=EntityFramework”,它想要“application name=EntityFramework”)到 web.config 中,问题就解决了。 :)

【讨论】:

谢谢,这确实是我的问题。我有一个使用 EF 访问数据库的项目和另一个项目 WCF。更改第一个项目的名称后,我的第一个项目的 App.config 中的 connectionString 已更改。所以我不得不在 web.config 中更改项目 WCF 中的 connectionString :) 来自 MSDN 关于docs.microsoft.com/en-us/dotnet/framework/data/adonet/… 的文档:The .NET Framework data provider for SQL Server (SqlClient) supports many keywords from older APIs, but is generally more flexible and accepts synonyms for many of the common connection string keywords. Entity Framework 连接字符串不具备这种灵活性,因此您只能使用它所期望的关键字。【参考方案23】:

当我解决了元数据问题时,我遇到了一个后续问题,即调用异常无法在 app.config 中找到 XXXEntities 的连接字符串(我的目标是不依赖于 app.config) .幸运的是,我发现在我的单元测试项目中引用 System.Data 清除了最后的障碍。总结一下:

    使用 nuget 将 Entity Framework 安装到您的单元测试项目中。 确保引用了 System.Data.Entity 和 System.Data。 按照这里的描述对连接字符串进行排序。 将连接字符串传递给分部类构造函数。

我现在将我的元数据保存在一个类库中,该类库可以从参考数据库进行更新,并且我可以在运行时将我的应用程序和单元测试指向任何服务器上的任何数据库。

附录:当我将我的 edmx 移动到一个文件夹时,我又遇到了错误。经过一番研究,我发现您希望您的元数据字符串看起来像:metadata=res://EPM.DAL/Models.EPM.csdl,其中 EPM.DAL 是程序集的名称,EPM.edmx 在模型文件夹。

【讨论】:

【参考方案24】:

遇到同样的问题,我从数据库重新创建了 edmx。 解决了我的问题。

【讨论】:

不幸的是,它解决并治疗了症状,而不是原因。【参考方案25】:

还有一个不带Reflector的快速查看模型名称的方法....查找目录

...obj/配置输出/edmxResourcesToEmbed

并检查 .csdl、.msl 和 .ssdl 资源文件是否存在。如果它们位于子目录中,则必须将子目录的名称添加到模型名称之前。

比如我的三个资源文件在一个子目录Data,所以我的连接字符串必须是

metadata=res://*/数据.MyModel.csdl|res://*/数据.MyModel.ssdl|res://*/数据.MyModel.msl;

(相对于元数据=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;)。

【讨论】:

这正是我的问题。为此浪费了几个小时。非常感谢您的简单解释 很好的答案,实际上解释了如何找到你的字符串。并显示子文件夹有“。”作为分隔符,而不是 '\' 或 '/'。【参考方案26】:

对我来说类似的问题。我的班级名称与我的文件名不同。生成的连接字符串包含类名而不是文件名。我的解决方案只是重命名我的文件以匹配类名。

【讨论】:

【参考方案27】:

我昨天遇到了这个问题,正在调试中查看我的代码和 SQL Profiler 的输出。

在我阅读并理解这篇文章之前,我无法理解的是,为什么 EntityFramework 在调用数据库时会抛出这个错误。我正在查看 SQL Profiler 中的数百行代码,试图找出数据库模型出了什么问题。我找不到任何我期待的电话,老实说,我不确定我在寻找什么。

如果您处于此位置,请检查连接字符串。我的猜测是,在 EntityFramework 创建其 SQL 之前,它会检查模型,在连接字符串的元数据部分中指定。就我而言,这是错误的。 EntityFramework 甚至没有达到数据库。

确保名称正确。一旦我把它整理好,我就会在 SQL Profiler 中看到调用,其中 ApplicationName 是“EntityFramework”,而 SQL 调用了预期的表。

【讨论】:

【参考方案28】:

一个糟糕的 app.config 或 web.config 文件可以做到这一点。我已将 app.config 连接字符串复制到我的 UI 中的 web.config 并最终输入:

<connectionStrings>
    <connectionStrings>
          <add name="name" connectionString="normalDetails"/>
    </connectionStrings>
</connectionStrings>

【讨论】:

【参考方案29】:

我只是没有引用包含 EDMX 文件的类库。

【讨论】:

这对我的特殊情况很有帮助,感谢@PeterX。【参考方案30】:

使用来自this blogpost的信息:

正如其他人所说, res:\\ 是指向您的资源的指针。要检查并确保您的资源名称正确,您可以使用像 DotPeek by JetBrains 这样的反编译器来打开您的 .dll 文件并查看您的资源文件。

或者您可以在调试时打开监视窗口并粘贴此代码以获取当前执行程序集中的资源名称数组。

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames()

话虽如此,元数据路径的格式应该类似于:

my-assembly-name/possibly-a-namespace.class-name.csdl or ssdl or msl

【讨论】:

以上是关于MetadataException:无法加载指定的元数据资源的主要内容,如果未能解决你的问题,请参考以下文章

JAVA无法加载指定的文件?

“无法加载指定的元数据资源”错误实体框架

由于错误 0xC001000A,无法加载包。说明:无法从 SQL Server 数据库加载指定的包

SQL Server Compact 错误:无法加载 DLL 'sqlceme35.dll'。指定的模块无法找到

java的软件无法启用 无法加载指定文件。

SSIS - 无法加载 DLL 'clrcompression.dll':找不到指定的模块