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

时间:2009-03-27 11:15:08

标签: c# .net entity-framework ado.net

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

有人有什么想法吗?

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

我尝试重新创建EDMX。我试过重新创建这个项目。我甚至尝试从头开始重新创建数据库。没有运气,无论如何。

44 个答案:

答案 0 :(得分:812)

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

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

简而言之,您的问题中没有足够的细节来提供准确的答案,但希望这些想法可以让您走上正确的道路。

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

答案 1 :(得分:344)

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

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

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

更改为

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

答案 2 :(得分:112)

当Edmx在一个项目中并且您从另一个项目中使用它时,您可以获得此异常。

原因是Res://*/是指向CURRENT程序集中资源的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文件的文件名。当资源具有与元数据值中指定的名称不同的名称时,它将不起作用。

答案 3 :(得分:60)

我有类似的错误。我重新创建了这个项目(长篇故事),并从旧项目中删除了所有内容。我之前没有意识到我的模型已经在名为“模型”的目录中,现在位于名为“模型”的目录中。一旦我在Web.Config中更改了连接:

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

到此:

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

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

答案 4 :(得分:25)

快速检查模型名称而不使用Reflector ....查找目录

  

... obj / {config output} / edmxResourcesToEmbed

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

例如,我的三个资源文件位于子目录数据中,因此我的连接字符串必须是

  

元数据= RES:// * / 数据 .MyModel.csdl | RES:// * / 数据 .MyModel.ssdl | RES:// * / < strong>数据 .MyModel.msl;

(与metadata = res://*/MyModel.csdl | res://*/MyModel.ssdl | res://*/MyModel.msl;)。

答案 5 :(得分:15)

我也有这个问题,这是因为我的web.config中的connectionstring与我的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字符串(注意最后的小差异 - 而不是“App=EntityFramework”它想要“application name=EntityFramework”)进入web.config并且问题是解决了。 :)

答案 6 :(得分:12)

当我意外地将edmx文件的构建操作(出现在IDE中的“属性”下)从“EntityDeploy”切换为“无”时,发生了这种情况。 EntityDeploy是为您填充元数据的内容:请参阅http://msdn.microsoft.com/en-us/library/cc982037.aspx

答案 7 :(得分:8)

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

非常容易错过 - 如果你重命名,请确保你获得一切 ....

答案 8 :(得分:6)

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

答案 9 :(得分:6)

我花了一整天时间来解决这个错误

如果您正在使用n-tear architecture

或者您尝试separate Models生成的EDMX表格DataAccessLayer DomainModelLayer

也许你会得到这个错误

  1. 首先排查问题的步骤是确保webconfig (UILayer)appconfig (DataAccessLayer)中的连接字符串相同
  2. 第二个非常重要的是 connection string

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

    这是问题

  3. 从地球上我得到Model或者我的连接字符串中的任何.csdl

    这里我的解决方案看图片

    enter image description here

    希望对你有所帮助

答案 10 :(得分:6)

当我在构建新的.edmx设计器之前不清理解决方案时,这会发生在我身上。因此,在构建新的.edmx设计器之前,请不要忘记清理解决方案。这有助于我跳过与此有关的更多问题。如果您是Visual Studio的新手,请提供以下导航详细信息。

  

点击->构建->清洁解决方案

     

然后点击->构建->重建解决方案

希望这会有所帮助。谢谢大家

答案 11 :(得分:6)

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

  1. 打开edmx文件
  2. 右键单击EDMX设计器的任何位置
  3. 选择属性
  4. 更新名为“元数据工件处理”的属性为“嵌入输出程序集”
  5. 这解决了我的问题。 问题是,当容器试图找到元数据时,它无法找到它。所以只需在同一个组件中进行。 如果您的edmx文件在另一个程序集中

    ,则此解决方案将不起作用

答案 12 :(得分:5)

我能够在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"

答案 13 :(得分:4)

最终解决方案(即使在其他两台机器上重建数据库,以及EDMX和其他杂物)也不使用第一版的Entity Framework。期待在.NET 4.0中再次对其进行评估。

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

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

更新2013-01-16 :转换到几乎完全使用EF Code First做法(即使使用现有数据库),此问题不再是问题。对我来说,这是一个可行的解决方案,可以减少自动生成的代码和配置的混乱,并增加我对产品的控制。

答案 14 :(得分:4)

我的问题和解决方案,症状是相同的“无法加载指定的元数据资源”,但根本原因不同。我在解决方案中有2个项目,一个是EntityModel,另一个是解决方案。我实际上删除并重新创建了EntityModel中的EDMX文件。

解决方案是我必须返回Web应用程序项目并将此行添加到配置文件中。新模型改变了一些必须在“其他”项目的Web.Config文件中复制的项目。旧的配置不再好了。

     <add name="MyEntities"
     connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;
                    provider=System.Data.SqlClient;
                    provider connection string=&quot;
                    data source=Q\DEV15;initial catalog=whatever;
                    user id=myuserid;password=mypassword;
                    multipleactiveresultsets=True;
                    application name=EntityFramework&quot;"
     providerName="System.Data.EntityClient" />

答案 15 :(得分:4)

经过数小时的谷歌搜索并尝试解决所有建议的解决方案都没有奏效。我在这里列出了几个解决方案。我也注意到了一个适合我的方法。 (我使用的是EF版本6.1.1和SQL Server 2014 - 但是使用的是较旧的数据库)

  1. 重建项目并重试。
  2. 关闭并打开VS - 我不知道这是如何工作的
  3. 确保您已将.EDMX文件放在目录中,请确保在ConnectionString中包含目录。例如我的是DAL文件夹。它看起来像这样:connectionString="metadata=res://*/DAL.nameModel.csdl|res://*/DAL.nameModel.ssdl|res://*/DAL.nameModel.msl;(这些是文件。看到它们你可以在解决方案资源管理器中切换显示所有文件,在〜/ obj / ..目录下)
  4. ...以及我尝试过的更多内容[例如:将EntityFramework版本恢复为更高版本(不确定)]

    对我有用的东西:

    来自这个article here,它帮助我解决了我的问题。我刚刚在EDMX文件中将ProviderManifestToken="2012"更改为ProviderManifestToken="2008"。要做到这一点:

    解决方案资源管理器

    1. 右键单击文件.edmx
    2. 以...打开
    3. 编辑XML
    4. 更改ProviderManifestToken =&#34; XXXX&#34;与2008年
    5. 我希望有所帮助。

答案 16 :(得分:3)

对于所有SelftrackingEntities用户, 如果您已遵循Microsoft Walk-through并将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项目程序集中),

因此,您应该使用 - &gt;

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

玩得开心。

答案 17 :(得分:3)

我编写了这个帮助器类来创建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;
    }
}

答案 18 :(得分:3)

在我的情况下,此问题与重命名我的模型的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'的文件夹中。

答案 19 :(得分:2)

如果您正在使用其他项目中的edmx,请在连接字符串中更改...

metadata=res://*/Data.DataModel.csdl

...到...

metadata=res://*/DataModel.csdl

答案 20 :(得分:2)

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

答案 21 :(得分:2)

异常是因为编译器指向不存在的元数据,因此只需将app.config connectionstring复制到Web.config ConnectionString

答案 22 :(得分:2)

有同样的问题,因为我重命名了一个程序集。

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

然后它运作得很好。

答案 23 :(得分:2)

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

答案 24 :(得分:1)

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

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

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

只需将缺少的引用添加到主项目即可解决此问题,无需编辑连接。

我希望这有助于其他人。

答案 25 :(得分:1)

有时我在项目中看到此错误。我通过

解决了

1-右键单击EDMX文件

2-选择Run Custom Tool选项

3-重建项目

答案 26 :(得分:1)

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

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

答案 27 :(得分:1)

我根本没有引用包含EDMX文件的类库。

答案 28 :(得分:1)

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

答案 29 :(得分:0)

在我的情况下,列出的答案都没有奏效,所以我发布了这个。

对于我的情况,在Visual Studio上构建并使用IIS Express运行它工作正常。但是,当我使用Nant脚本进行部署时,作为一个独立的网站会出错。我尝试了上面的所有建议,然后意识到由nant脚本生成的DLL远小于VS生成的DLL。然后我意识到Nant无法找到.csdl,.msl和.ssdl文件。那么有两种方法可以解决这个问题,一种是在visual studio生成它们之后复制所需的文件,并在构建部署中包含这些文件。然后在Web.config中,将path指定为:

"metadata=~/bin/MyDbContext.csdl|~/bin/MyDbContext.ssdl|~/bin/MyDbContext.msl;provider=System.Data.SqlClient;...."

这假设您已手动将文件复制到正在运行的网站的bin目录中。如果它位于不同的目录中,则相应地修改路径。 第二种方法是在Nant脚本中执行EdmGen.exe并生成文件,然后将它们作为资源包含在下面的示例中: https://github.com/qwer/budget/blob/master/nant.build

答案 30 :(得分:0)

将大型解决方案从Source Control Explorer中的一个文件夹移动到另一个文件夹后,我遇到了此问题。我们不会将包文件夹检查到Team Foundation中,因此我认为VS会自动下载包。这将我的EF表格v6.1.2升级到v6.1.3。

当我降级到原来的v6.1.2时,问题就消失了。

答案 31 :(得分:0)

在我的情况下,这是因为我使用EntityConnectionStringBuilder构建连接字符串。确保您的Metadata属性使用模型名称(包括命名空间)

答案 32 :(得分:0)

我也遇到这个问题,我只是清理并重建可以正常工作的解决方案。

答案 33 :(得分:0)

我在2019年9月27日遇到了同样的问题。

我的API位于以.net框架为目标的Dot net核心中。 edmx在另一个类库中,该类库仅在.net框架中。

我观察到,由于某种原因,当我尝试从API ..调用该edmx时,出现了该错误。

我所做的是,转到API的obj文件夹并删除所有内容。 然后清理API项目,然后重试,对我有用。

答案 34 :(得分:0)

Just type path as follows instead of {Path.To.The.}: res:///{Path.To.The.}YourEdmxFileName.csdl|res:///{Path.To.The.}YourEdmxFileName.ssdl|res://*/{Path.To.The.}YourEdmxFileName.msl

答案 35 :(得分:0)

当我的emdx文件被prebuild命令删除时,我收到此错误,非常简单。花了一些时间才意识到这很简单。

答案 36 :(得分:0)

使用this blogpost中的信息:

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

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

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

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

{my-assembly-name} / {possible-a-namespace}。{class-name}。{csdl或ssdl or msl}

答案 37 :(得分:0)

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

在我阅读并理解这篇文章之前,我无法理解的是EntityFramework在调用数据库时抛出此错误的原因。我正在查看SQL Profiler中的数百行,试图找出数据库模型的错误。我找不到像我期待的那样的电话,说实话我不确定我在寻找什么。

如果您处于此位置,请检查连接字符串。我的猜测是,在EntityFramework创建其SQL之前,它将检查在连接字符串的元数据部分中指定的模型。在我看来这是错误的。 EntityFramework甚至没有像DB一样。

确保名称正确无误。一旦我解决了这个问题,我就会看到SQL Profiler中的调用,其中ApplicationName是'EntityFramework',SQL调用了预期的表。

答案 38 :(得分:0)

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

答案 39 :(得分:0)

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

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

我现在将我的元数据放在可以从引用数据库更新的类库中,我可以在运行时将我的应用程序和单元测试指向任何服务器上的任何数据库。

附录:当我将edmx移动到文件夹时,我再次收到错误。经过一些研究后,我发现您希望元数据字符串看起来像:metadata = res://EPM.DAL/Models.EPM.csdl,其中EPM.DAL是程序集的名称,EPM.edmx位于models文件夹。

答案 40 :(得分:0)

至于我,我已将数据访问层和用户界面层分开了。 所以我为每一层都有实体连接字符串。

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

Unable to load the specified metadata resource

所以我使这两个层(DAL,UI)的连接字符串相同,它完美无缺。

我的解决方案是让所有连接字符串无论在哪里都是相同的

答案 41 :(得分:0)

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

    [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

答案 42 :(得分:0)

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

示例:

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

答案 43 :(得分:0)

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