EntityFramework t4模板 - XML文档

时间:2013-12-11 15:01:35

标签: c# entity-framework entity-framework-5 t4 xml-comments

我的EDMX文件存在以下问题。

在其中我已经为属性和实体编写了一些文档,但是我的EF 5的t4模板不会生成这些值。

我想要的结果应该是

public class Person
{
    /// <summary>
    /// Hello World Summary!!
    /// </summary>
    /// <remarks>
    /// Hello World Remarks!!
    /// </remarks>
    public string Name { get; set; }
}

但我只能

public class Person
{
    public string Name { get; set; }
}

如果不是这样,我为什么还能在edmx文件中设置文档属性。

3 个答案:

答案 0 :(得分:9)

似乎实体框架不会使用代码文档为您生成对象,而且我无法在nuget上看到解决方案,这是一种耻辱。

您可以修改T4模板,为您完成此操作而不会有太多麻烦。为了帮助您入门,如果您为实体打开T4模板,并找到看起来像这样的行(关于第74行):

    <#=codeStringGenerator.Property(edmProperty)#>

然后将其更改为:

<# if (edmProperty != null && edmProperty.Documentation != null) {#>
/// <summary>
/// <#= edmProperty.Documentation.Summary #>
/// </summary>
/// <remarks>
/// <#= edmProperty.Documentation.LongDescription #>
/// </remarks>
<# } #>
    <#=codeStringGenerator.Property(edmProperty)#>

这将为您的属性生成文档。

如果你去看起来像这样的那条线(关于我的第28行):

<#=codeStringGenerator.EntityClassOpening(entity)#>

然后将其更改为:

<# if (entity != null && entity.Documentation != null) {#>
/// <summary>
/// <#= entity.Documentation.Summary #>
/// </summary>
/// <remarks>
/// <#= entity.Documentation.LongDescription #>
/// </remarks>
<# } #>
<#=codeStringGenerator.EntityClassOpening(entity)#>

这应该会为您提供课程文档。

可能还有其他几个需要更新的地方(比如复杂和导航属性),但它应该可以帮到你。

马特

答案 1 :(得分:1)

这是我对此的看法。

在.tt文件中生成的CodeStringGenerator类中,我添加了此方法:

private string Comments(EdmMember member)
{
    string comments = member.Documentation != null
        ? (string.IsNullOrEmpty(member.Documentation.Summary)
            ? ""
            : @"
/// <summary>
/// " + member.Documentation.Summary.Replace("\n", Environment.NewLine + "    /// ") + @" 
/// </summary>
")
            +
            (string.IsNullOrEmpty(member.Documentation.LongDescription)
            ? ""
            : @"/// <remarks>
/// " + member.Documentation.LongDescription.Replace("\n", Environment.NewLine + "    /// ") + @"
/// </remarks>
")
        : "";
    return comments;
}

我承认这种方法有两个问题:a)它假设一定程度的缩进,尽管这是属性的预期缩进级别,b)如果没有Summary,则在注释之前添加额外的行。但这不可能发生。

然后,我从生成简单和导航属性的方法中调用此方法:

public string Property(EdmProperty edmProperty)
{
    string comments = Comments(edmProperty);
    return string.Format(
        CultureInfo.InvariantCulture,
        @"{5}{0} {1} {2} {{ {3}get; {4}set; }}",
        Accessibility.ForProperty(edmProperty),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)),
        comments);
}

public string NavigationProperty(NavigationProperty navProp)
{
    string comments = Comments(navProp);
    var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{5}{0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
        navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        _code.Escape(navProp),
        _code.SpaceAfter(Accessibility.ForGetter(navProp)),
        _code.SpaceAfter(Accessibility.ForSetter(navProp)),
        comments);
}

答案 2 :(得分:0)

我想向Matt Mhetton的答案添加更多细节,因为我目前的项目配置(CA和Style cop)一切都必须记录下来。

一方面,您必须在设计器中为要记录的所有内容添加文档属性(类,简单属性,复杂属性和导航属性)

另一方面,你必须打开你创建的WhateverModel.tt并编辑它以包含文档,我会一步一步地解释它:

1.-对于类文档,请查找:

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<#=codeStringGenerator.EntityClassOpening(entity)#>

(在我的情况下是第26行)并将你的评论放在这两行之间:

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<# if (entity != null && entity.Documentation != null) {#>
/// <summary>
/// <#= entity.Documentation.Summary #>
/// </summary>
<# } #>
<#=codeStringGenerator.EntityClassOpening(entity)#>

2.-对于构造函数文档,查找public <#=code.Escape(entity)#>() thaqt生成构造函数的内容,因此请将文档放在该行之前,如下所示:

<# if (entity != null && entity.Documentation != null) {#>
    /// <summary>
    /// <#= entity.Documentation.Summary #>
    /// </summary>
<# } #>
    public <#=code.Escape(entity)#>()
    {

3.-要记录每个属性查找foreach (var edmProperty in simpleProperties),此外观将生成属性代码,因此它应如下所示:

foreach (var edmProperty in simpleProperties)
        {
#>
<# if (edmProperty != null && edmProperty.Documentation != null) {#>    
    /// <summary>
    /// <#= edmProperty.Documentation.Summary #>
    /// </summary>
<# } #>
    <#=codeStringGenerator.Property(edmProperty)#>
<#

        }

(注意:这是针对简单属性的,但对于复杂属性来说将是相同的方式......)

4.-对于导航属性完全相同,请查找foreach (var navigationProperty in navigationProperties)并添加如下文档:

foreach (var navigationProperty in navigationProperties)
        {
#>
<# if (navigationProperty != null && navigationProperty.Documentation != null) {#>
    /// <summary>
    /// <#= navigationProperty.Documentation.Summary #>
    /// </summary>
<# } #>
    <#=codeStringGenerator.NavigationProperty(navigationProperty)#>
<#

        }

4.-最后但并非最不重要的是,如果您还需要在上下文类中使用文档,则可以使用此方法(查找<# if (code.Escape(container) != null) {#>):

<# if (code.Escape(container) != null) {#>
/// <summary>
/// Represents <#= code.Escape(container) #>
/// </summary>
<# } #>
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{

<# if (code.Escape(container) != null) {#>
    /// <summary>
    /// Initializes a new instance of the <see cref="<#= code.Escape(container) #>"/> class.
    /// </summary>
<# } #>
    public <#=code.Escape(container)#>()
    : base("name=<#=container.Name#>")
    {
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
        this.Configuration.LazyLoadingEnabled = false;
<#
}
#>
    }

    /// <summary>
    /// On Model Creating
    /// </summary>
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

<#
    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
    {
#>

   <# if (code.Escape(entitySet) != null) {#>
    /// <summary>
    /// Gets or sets the <#=code.Escape(entitySet)#>
    /// </summary>
    <# } #>

我希望Matt Whetton的回答对我有帮助(谢谢Matt)。