EF 代码生成模板:发现差异?

Posted

技术标签:

【中文标题】EF 代码生成模板:发现差异?【英文标题】:EF code generation template: spot the difference? 【发布时间】:2015-05-25 11:56:57 【问题描述】:

我前段时间使用旧的 ObjectContext 模板创建了一个 EF 项目(首先是 DB)。这会将所有内容生成一个巨大的 honkin' 文件。这样做有一些缺点,比如如果我想查看文件,IDE 需要一段时间才能将其全部加载到内存中,而修改需要一段时间才能刷新。另外,在源代码控制历史记录中很难一目了然:如果我想知道发生了什么变化,我必须在一个巨大文件的两个版本之间进行文件差异,而不是简单地查看孤立文件中的变化,生成为每班一个。

所以我决定尝试创建一个代码模板来生成相同代码,每个类只有一个文件。而且我认为我做得很好,因为代码编译得很好......但是当我打开应用程序时,我得到一个错误:

指定的架构无效。错误:

关系“AssessmentSchool”的属性包含角色“Assessment”,其类型“SchoolManagement.BL.Assessment”对关系结束无效。将 End Role 更改为 EntityType。

关系“AssessmentSchool”的属性包含角色“School”,其类型“SchoolManagement.BL.School”对关系结束无效。将 End Role 更改为 EntityType。

然后它继续列出系统中的每个多对多交集表(两次;关系的每一端一个)。在AssessmentSchool 的情况下,该表只有一个AssessmentID 和一个SchoolID

于是我对比了旧MyContext.designer.cs中的关系声明,找到了任何提到关系的地方,并与新代码进行了对比。你能看出区别吗?

旧数据上下文:

[assembly: EdmRelationshipAttribute("SchoolManagement.BL", "AssessmentSchool", "Assessment", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(SchoolManagement.BL.Assessment), "School", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(SchoolManagement.BL.School))]

新的数据上下文:

[assembly: EdmRelationshipAttribute("SchoolManagement.BL", "AssessmentSchool", "Assessment", RelationshipMultiplicity.Many, typeof(SchoolManagement.BL.Assessment), "School", RelationshipMultiplicity.Many, typeof(SchoolManagement.BL.School), false)]

(是的,有一些小的区别:新文件在文件顶部有一个using System.Data.Metadata.Edm 语句,而isForeignKey 参数的false 无论如何都是默认值。我尝试手动删除它参数,它没有任何区别。)

OLD 评估类:

[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[EdmRelationshipNavigationPropertyAttribute("SchoolManagement.BL", "AssessmentSchool", "School")]
public EntityCollection<School> Schools

    get
    
        return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<School>("SchoolManagement.BL.AssessmentSchool", "School");
    
    set
    
        if ((value != null))
        
            ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<School>("SchoolManagement.BL.AssessmentSchool", "School", value);
        
    

新的评估课程:

    [XmlIgnoreAttribute()]
    [SoapIgnoreAttribute()]
    [DataMemberAttribute()]
    [EdmRelationshipNavigationPropertyAttribute("SchoolManagement.BL", "AssessmentSchool", "School")]
    public virtual EntityCollection<School> Schools
    
        get
        
            return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<School>("SchoolManagement.BL.AssessmentSchool", "School");
        
        set
        
            if ((value != null))
            
                ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<School>("SchoolManagement.BL.AssessmentSchool", "School", value);
            
        
    

对称关系在Class类中也有,这里不再赘述。

这段代码看起来和我一模一样,它编译得很好,但它只是抛出了上面的运行时错误。显然,我在某个地方还缺少另一个技巧。但是什么?

【问题讨论】:

您发布的代码似乎是相同的。我的猜测是差异在另一个地方。我的建议是手动分解生成的单体代码,看看它是否有效,然后比较每个文件。我的猜测是关系在某个不明显的地方变得一团糟。 【参考方案1】:

发现问题:我正在生成没有装饰器的 EntityObject 类:

[EdmEntityTypeAttribute(NamespaceName="SchoolManagement.BL", Name="Assessment")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Assessment : EntityObject

  ...

【讨论】:

接受您自己的答案,以便正确过滤问题。很高兴你解决了!

以上是关于EF 代码生成模板:发现差异?的主要内容,如果未能解决你的问题,请参考以下文章

EF 模板化代码生成有啥用途?

EF生成实体模板改良

通过T4模板解决EF模型序列号的循环引用问题

使用T4模板为EF框架添加实体根据数据库自动生成字段注释的功能

EF 代码生成:如何让系统枚举作为 EdmEnumType 工作?

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