我的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文件中设置文档属性。
答案 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)。