关于C#:元数据异常:无法加载指定的元数据资源

MetadataException: Unable to load the specified metadata resource

突然间,我在实例化生成的ObjectContext类时,得到了一个MetadataException。app.config中的连接字符串看起来是正确的-自上次工作以来一直没有更改-我尝试从基础数据库重新生成一个新模型(edmx文件),但没有更改。

有人有什么想法吗?

进一步的详细信息:我没有更改任何属性,没有更改任何输出程序集的名称,也没有尝试在程序集中嵌入EDMX。我从下班到回来只等了10个小时。然后它就不起作用了。

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


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

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

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

更新:我写了一篇博文,上面有更完整的故障排除步骤。


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

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

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

改为

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


当EDMX在一个项目中,而您正从另一个项目中使用它时,您可以得到这个异常。

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

您不需要指定"*",而是需要提供程序集的全名(包括公钥标记)。如:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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();
}

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


我也有类似的错误。我重新创建了这个项目(说来话长),并把旧项目的所有内容都改过来了。我以前没有意识到我的模型在一个名为"model"的目录中,现在在一个名为"models"的目录中。一旦我更改了web.config中的连接:

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

对此:

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

一切正常(把Model改为Models。注意,我必须改变这三个位置。


还有一种快速检查没有反射镜的型号名称的方法……查找目录

...obj/{config output}/edmxResourcesToEmbed

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

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

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

(与metadata=res://*/mymodel.csdl res://*/mymodel.ssdl res://*/mymodel.msl;)相比。


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

App.config:

1
 

Web.config:

1
 

修复的方法是简单地将app.config字符串复制到web.config中(注意结尾处的小差异,而不是"EDOCX1"(0)),问题解决了。:)


当我意外地将edmx文件的构建操作(显示在IDE的属性下)从"entitydeploy"切换到"none"时,发生了这种情况。EntityDeploy是为您填充元数据的工具:请参阅http://msdn.microsoft.com/en-us/library/cc982037.aspx


我刚刚愉快地度过了30分钟。我重命名了Entities对象,重命名了配置文件中的条目,但还有更多…您还必须更改对CSDL的引用

很容易错过-如果你正在重命名,确保你得到所有东西…


对于我的情况,通过更改EDMX文件的属性来解决这个问题。

  • 打开EDMX文件
  • 右键单击EDMX设计器的任何位置
  • 选择属性
  • 将名为"元数据项目处理"的属性更新为"嵌入到输出程序集中"
  • 这为我解决了问题。问题是,当容器试图查找元数据时,它找不到它。所以只要把它放在同一个组件里就行了。如果您的EDMX文件位于其他程序集中,则此解决方案将不起作用。


    我也有同样的问题。我用Reflector查看了编译后的DLL,发现资源的名称不正确。我改名了,现在看起来很好。


    我花了一整天的时间来研究这个错误

    如果你和n-tear architecture合作

    或者您试图将EDMX生成的cx1〔1〕形成到DomainModelLayer的数据访问层。

    也许你会得到这个错误

  • 第一个故障排除步骤是确保webconfig (UILayer)appconfig (DataAccessLayer)中的连接字符串相同。
  • 第二,这一点非常重要

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

    哪个是问题

  • 我到底从哪里得到了Model或其他什么东西。csdl在我的连接字符串中,它们在哪里?

    我来看看我们的解决方案

    enter image description here

    希望能帮到你


    当我在构建新的.edmx设计器之前不清理解决方案时,就会发生这种情况。所以,在构建新的.edmx设计器之前,不要忘记清理解决方案。这有助于我跳过这个问题。以下是您在Visual Studio中是新用户时提供的导航详细信息。

    Click->Build->Clean Solution

    Then Click->Build->Rebuild Solution

    希望这有帮助。谢谢大家


    我在Visual Studio 2010的vb.net(asp.net)4.0中解决了这个问题。

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

    我唯一缺少的是连接字符串中的"应用程序代码"。

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


    经过数小时的谷歌搜索和尝试解决所有建议的解决方案都不起作用。我在这里列出了几个解决方案。我也注意到了那个为我工作的人。(我使用的是EF版本6.1.1和SQL Server 2014,但是一个较旧的数据库)

  • 正在重建项目,然后重试。
  • 关闭和打开vs-我不知道这是怎么回事
  • 确保已将.edmx文件放在目录中,确保在connectionString中包含目录。例如,mine位于dal文件夹中。所以看起来是这样的:connectionString="metadata=res://*/DAL.nameModel.csdl|res://*/DAL.nameModel.ssdl|res://*/DAL.nameModel.msl;(这些是文件。要查看这些文件,可以在解决方案资源管理器的~/obj/下切换"显示所有文件"。目录)
  • …还有许多我尝试过的[例如:将EntityFramework版本还原为更高版本(不确定)]

    为我工作的是:

    从本文中,它帮助我解决了我的问题。我刚在EDMX文件中将我的ProviderManifestToken="2012"改为ProviderManifestToken="2008"。这样做:

    解决方案管理器

  • 右键单击文件.edmx
  • 打开…
  • 编辑器XML
  • 将providerManifestToken="XXXX"更改为2008年
  • 希望有帮助。


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

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

    V1.0错误?:无法加载指定的元数据资源。脚本!=模型

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


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

    解决方案是我必须返回到Web应用程序项目并将这一行添加到配置文件中。新模型改变了一些必须在"另一个"项目的web.config文件中复制的项。旧的配置不再好。

    1
    2
    3
    4
    5
    6
    7
    8
    9
         <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" />


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

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

    希望它能帮助别人。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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;
        }
    }

    在我的例子中,这个问题与重命名我的模型的EDMX文件有关…更正csdl/ssdl/msl文件的app.config连接字符串修复了我的问题。

    如果使用EF4.0设计器生成CSDL/SSDL/MSL,这3个"文件"实际上将存储在模型的主EDMX文件中。在这种情况下,Waqas的文章基本上是有根据的。重要的是要理解,在他的示例中,"modelu name"需要更改为模型的.edmx文件的当前名称(不带.edmx)。

    此外,如果您的EDMX文件不在项目的根级别,则需要在模型名称前面加上相对路径,例如。

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

    将指定csdl/ssdl/msl xml存储在模型文件"widgetmodel.edmx"中,该文件存储在名为"mymodel"的文件夹中。


    对于你们所有的SelftrackingEntities用户,如果您已经按照Microsoft的说明将对象上下文类划分为wcf服务项目(通过链接到context.tt),因此此答案适用于您:

    本文中显示的部分答案包括以下代码:

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

    不会为你工作的!!原因是YourObjectContextType.Assembly现在位于不同的程序集中(在wcf项目程序集中)。

    所以你应该用——>

    1
    ClassTypeThatResidesInEdmProject.Assembly.FullName

    玩得高兴。


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

    我还必须在project properties/assemblyinfo.cs中的assemblyTitle和assemblyProduct属性中重命名它,还必须删除并重新添加对edmx文件的引用。

    然后它工作得很好。


    我在这个错误消息上遇到了问题。关闭并重新打开Visual Studio 2010,解决了我的问题。


    例外是因为编译器指向不存在的元数据,所以只需将app.configconnectionstring复制到Web.configconnectionstring


    由于有同样的问题,我从数据库重新创建了EDMX。解决我的问题。


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


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

    尽管根据需要重新添加所有*项目引用之后编译的解决方案,但在启动网站时会引发错误。

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

    只需向主项目添加缺少的引用就解决了这个问题,根本不需要编辑连接。

    我希望这能帮助别人。


    差的app.config或web.config文件可以做到这一点。我已将app.config连接字符串复制到我的用户界面中的web.config,结果输入:

    1
    2
    3
    4
    5
    <connectionStrings>
        <connectionStrings>
             
        </connectionStrings>
    </connectionStrings>

    如果您使用的是来自不同项目的EDMX,那么在连接字符串中,更改…

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

    为了…

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

    有时我在我的项目中看到这个错误。我解决了这个问题。

    1-右键单击EDMX文件

    2-选择Run Custom Tool选项

    3-重建项目


    我也有和Rick一样的问题和解决方案,除了我正在将一个现有的.edmx导入到一个新项目中,虽然基本名称空间并不重要,但它被导入到一个不同的子目录中,所以我还必须在三个位置更新web.config中的连接字符串,以包括不同的子目录命名:


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


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

    例子:

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
        [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


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

  • 使用nuget将实体框架安装到单元测试项目中。
  • 确保引用System.Data.Entity和System.Data。
  • 按照这里的描述对连接字符串进行分类。
  • 将连接字符串传递给分部类构造函数。
  • 我现在把元数据放在一个类库中,这个类库可以从引用数据库更新,并且我可以在运行时将我的应用程序和单元测试指向任何服务器上的任何数据库。

    附录:当我把我的EDMX移到一个文件夹时,我又出错了。经过一番研究,我发现您希望元数据字符串看起来像:metadata=res://epm.dal/models.epm.csdl,其中epm.dal是程序集的名称,epm.edmx在models文件夹中。


    我也面临这个问题,我只是清理和重建的解决方案,工作得很好。


    我也有类似的问题。我的类名与我的文件名不同。生成的ConnectionString具有类名,而不是中的文件名。对我来说,解决方法就是重新命名文件以匹配类名。


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

    在阅读和理解本文之前,我无法理解的是EntityFramework在调用数据库时抛出此错误的原因。我查看了SQL事件探查器中的数百行,试图找出数据库模型的错误所在。我找不到任何我期待的电话,老实说,我不确定我在找什么。

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

    确保名称正确。当我解决了这个问题后,我在SQL事件探查器中看到了调用,其中applicationname是"entityframework",SQL调用了预期的表。


    使用此blogpost中的信息:

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

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

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

    也就是说,元数据路径的格式应该类似于:

    我的程序集名称/可能是-a-命名空间.类名.csdl或ssdl或msl


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


    只需按以下方式键入path,而不是path.to.the.:res:///path.to.the.youredmxmfilename.csdl res://path.to.the.youredmxmfilename.ssdl res:/*/path.to.the.youredmxmfilename.msl


    在我的例子中,这是因为我正在使用EntityConnectionsTringBuilder构建连接字符串。确保元数据属性使用模型名称(包括命名空间)


    在将一个大型解决方案从源代码管理资源管理器中的一个文件夹移动到另一个文件夹之后,我遇到了这个问题。我们不检查包文件夹到Team Foundation,所以我认为VS下载的包是自动的。这将我的EF表V6.1.2升级到了V6.1.3。

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


    在我的例子中,所有列出的答案都不起作用,所以我要发布这个。

    对于我的案例,在Visual Studio上构建并使用IIS Express运行它可以很好地工作。但是,当我部署使用南特脚本作为独立的网站时,出现了错误。我尝试了以上所有的建议,然后意识到由nant脚本生成的dll比由vs.生成的要小得多,然后我意识到nant找不到.csdl、.msl和.ssdl文件。因此,有两种方法可以解决这个问题,一种是在Visual Studio生成所需的文件之后复制它们,并将这些文件包含在构建部署中。然后在web.config中,指定路径为:

    1
    "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网站


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

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

    1
    Unable to load the specified metadata resource

    所以我为这两层(dal,ui)制作了相同的连接字符串,它工作得很完美。

    我的解决方案是使所有连接字符串都保持不变,无论它们出现在何处。