使用 EF4 的 POCO 模板时“找不到元数据信息”?

Posted

技术标签:

【中文标题】使用 EF4 的 POCO 模板时“找不到元数据信息”?【英文标题】:"Metadata information not found" while using EF4's POCO Template? 【发布时间】:2011-01-15 21:57:32 【问题描述】:

我刚刚为 EF4 安装了 POCO 模板。我的模型中有一个实体 AnnouncementText,并且 T4 文件似乎已正确生成。当我访问自动生成的属性MyObjectContext.AnnouncementTexts 时,尝试访问这个新实体会引发以下错误:

InvalidOperationException:找不到实体类型“MyNamespace.AnnouncementText”的映射和元数​​据信息。

AnnouncementText POCO 上的属性似乎与数据库中的列匹配,并且我没有更改任何自动生成的代码。

堆栈跟踪是:

   at System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType)
   at System.Data.Objects.ObjectContext.GetEntitySetForNameAndType(String entitySetName, Type entityCLRType, String exceptionParameterName)
   at System.Data.Objects.ObjectContext.CreateObjectSet[TEntity](String entitySetName)
   at MyNamespace.MyObjectContext.get_AnnouncementTexts() in C:\<snip>\MyObjectContext.Context.cs:line 65
   at MyNamespace.Class1.Main() in C:\<snip>\Class1.cs:line 14

如果我从解决方案中删除 .tt 文件并在模型上启用代码生成,我可以毫无问题地访问该属性。

这是我的代码,以防万一:

using (var context = new MyObjectContext())
   foreach (var at in context.AnnouncementTexts)
      Console.WriteLine(at.Title);

有什么想法可能是错的吗?

【问题讨论】:

您的项目中有多个 edmx 文件吗? 恐怕我只是添加了一个 edmx 来测试 iirc 的功能,尽管自从发布这个问题后我已经转移到 VS 2010 RC1。由于 POCO 模板才可用几天,我还没有机会查看我的问题是否仍然存在。 【参考方案1】:

更改视图 sql 后遇到类似问题。必须在 tt 文件上右键才能更新它并修复它。

【讨论】:

【参考方案2】:

在集成各种项目时,我遇到了类似的问题。 问题是我有不止一个edmx,因为我有很多项目。

连接字符串相同,但命名空间不同。

要解决此问题,请选择要使用的连接之一并更改其他连接。请注意,您需要在 Designer.cs 和 xml 文件中进行更改。

【讨论】:

【参考方案3】:

我们在不使用 edmx 模型时遇到了同样的问题,我们使用的是 EF powertools beta 2,使用逆向工程代码优先功能来生成我们的实体、上下文和视图。

我们有一个奇怪的行为,在几台机器上的团队中,生成的编译视图的哈希值是不同的,然后在 TFS 团队构建与其他机器上相同的情况下,我们会得到如下异常。问题是基于什么电动工具为编译视图生成哈希?并且我们可以更改它是一致的,我们使用带有 EF 4.3.1 的 power tools beta 2 , system.data .v4.0.30319 ,针对使用 devart oracle 驱动程序的 Oracle db。

上下文生成视图

//--------------------------------------------- ----------------------------------

//

//此代码由工具生成。

// 运行时版本:4.0.30319.551

// 对该文件的更改可能会导致不正确的行为,如果重新生成代码将丢失。

//

//--------------------------------------------- ----------------------------------

[程序集:System.Data.Mapping.EntityViewGenerationAttribute(typeof(Edm_EntityMappingGeneratedViews.ViewsForBaseEntitySetsC6473E0A11A196A36CC5839589DE2DE553F202E361016A89F2142797168B2534))]

命名空间 Edm_EntityMappingGeneratedViews

/// <Summary>

/// The type contains views for EntitySets and AssociationSets that were generated at design time.

/// </Summary>

public sealed class ViewsForBaseEntitySetsC6473E0A11A196A36CC5839589DE2DE553F202E361016A89F2142797168B2534 : System.Data.Mapping.EntityViewContainer



    /// <Summary>

    /// The constructor stores the views for the extents and also the hash values generated based on the metadata and mapping closure and views.

    /// </Summary>

    public ViewsForBaseEntitySetsC6473E0A11A196A36CC5839589DE2DE553F202E361016A89F2142797168B2534()

    

        this.EdmEntityContainerName = "Context";

        this.StoreEntityContainerName = "CodeFirstDatabase";

        this.HashOverMappingClosure = "2c6bbce22db7c9c65f8a70c5a1bae1225522a2124aad50e74bdc186ce8c70508";

        this.HashOverAllExtentViews = "26cad9d7334571a0116f89413345d00ec8e031706228df6e653c7b6396c94591";

        this.ViewCount = 56;

    

例外:

System.Data.EntityCommandCompilationException:System.Data.EntityCommandCompilationException:准备命令定义时出错。有关详细信息,请参阅内部异常。 ---> System.Data.MappingException: EntityContainer 'Context' 的映射和元数​​据信息不再与用于创建预生成视图的信息匹配..

【讨论】:

【参考方案4】:

我最近在将我的 EDMX 文件移动到解决方案中的新位置时再次遇到了同样的错误。显然,在处理 EDMX 文件时有几个不同的命名空间。您在创建初始 EDMX 文件 (N1) 时通过向导输入的命名空间,另一个出现在 SSDL 中的命名空间看起来像这样 (N2):

<Schema Namespace="..." ..

然后是生成代码的命名空间,可以(可选)在设计器中指定 (N3),最后是编译到最终程序集 (N4) 中的资源的隐藏命名空间。

据我所知,命名空间 N2 仅在 SSDL 内部真正相关。我相信这个命名空间一开始是 N1 - 你最初在向导中输入的那个。

同样,命名空间 N3 仅与 C# 命名空间通常的方式相关。

这是有问题的部分。类别 N4 命名空间是 EDMX 所在目录的函数(相对于您的项目目录) .你可能会想,那又怎样?事实证明,您的 App.config 文件中也引用了这些命名空间!具体来说,寻找这样的部分:

connectionString="metadata=res://*/Database.Master.csdl|...

读取“Database.Master.csdl”的部分是您的 CSDL 资源的名称。如果这些资源名称不同步,您将收到与上述类似的错误,或者可能:

在映射和元数​​据信息中找不到指定的默认 EntityContainer 名称“[name]”。

简单的解决方案是更改 App.config 以为 EF 映射(CSDL、SSDL 和 MSL)的每个部分指定正确的资源名称。如果您不确定这些名称到底是什么,请查看 ILSpy 或 dotPeek 中已编译程序集的资源。

【讨论】:

太棒了,正是我想要的。我已将我的 edmx 文件移动到一个新文件夹中,实际上,EF 的元数据连接字符串中缺少的命名空间信息是罪魁祸首。谢谢! 在将我的数据库代码从它自己的文件夹重构到它自己的类库后,我收到错误“无法加载指定的元数据资源”。这个答案解释并解决了这个问题。谢谢!【参考方案5】:

在解决方案资源管理器中,右键单击实体数据模型文件 (.edmx),然后单击“打开方式”。将打开一个对话框,让您选择一个程序来打开文件。 选择或双击“XML(文本)编辑器”。

现在您正在查看 EDM 文件的 XML 版本,您可以在其中轻松编辑“EntityContainer”名称。

如果您更改了 webconfig 文件中的连接字符串,请确保“DefaultContainerName”是该 XML 文件中“EntityContainer”部分的名称。

通常当您更新 *.Designer.cs 文件中的 defaultContainerName 时,它​​不会更新 XML 文件。所以你必须手动完成。

【讨论】:

【参考方案6】:

我通过在其中创建一个单独的项目和一个 edmx 来扩展 NopCommerce。 POCO 模板用于生成我的自定义ObjectContext 后代类。

我验证了所有属性、所有命名空间,但仍然出现上述异常。

重点是删除 MyModel.Designer.cs 文件,该文件生成另一个 ObjectContext 后代类(具有另一个名称并位于另一个命名空间内)。

【讨论】:

【参考方案7】:

如果您将 EDMX 文件复制到另一个项目,则构建操作(在“属性”窗格中)将恢复为目标项目中的默认值“无”,这可能导致“实体容器名称...无法找到”错误,这是因为没有生成资源。 (如果是这种情况,当您在 Reflector 中打开包含模型的 DLL 时,将没有资源。)将 Build Action 设置为“EntityDeploy”并重新构建解决方案将更正此问题。

【讨论】:

【参考方案8】:

不确定这个......它看起来有点奇怪,所以这是一个很长的镜头。

但有时偶尔调用 ObjectContext.MetadataWorkspace.LoadFromAssembly() 会有所帮助。

即使没有提供跟踪样式输出的第二个重载。

Assembly assembly = typeof(AnnouncementText).Assembly;
context.MetadataWorkspace.LoadFromAssembly(
    assembly, 
    (message) => Console.WriteLine(message)
);
foreach(var at in context.AnnouncementTexts)
   ...

然后看看你收到了什么消息(如果有的话)。

希望对你有帮助

亚历克斯

【讨论】:

好吧,在这种情况下,这似乎没有做(或打印)任何事情。我还尝试删除 POCO 的东西,并在您的示例代码中使用默认实体生成,恐怕在这种情况下我也没有看到任何输出。感谢您的尝试!在黑暗中拍摄是非常受欢迎的,呵呵。

以上是关于使用 EF4 的 POCO 模板时“找不到元数据信息”?的主要内容,如果未能解决你的问题,请参考以下文章

EF4 POCO:快照与 WCF 上的自我跟踪

保存 EF4 POCO 对象的更改时更新关系

EF4 Poco 问题映射类型相同的名称相同的程序集不同的命名空间

EF4 将 DynamicProxies 转换为基础对象

EF4 CTP5 POCO 中的软删除、导航属性

MVC3 应用程序/服务层/存储库层/POCO 类/EF4 - 问题!