在Entity Framework代码中添加自定义属性属性

时间:2009-06-26 19:07:50

标签: entity-framework custom-attributes

有没有办法在EF生成的代码中为属性添加自定义属性?我唯一可以看到的是一个合理的解决方案是提出一个自定义的T4模板。但是,由于属性的性质,不可能为每个EF属性确定正确的属性参数。

6 个答案:

答案 0 :(得分:35)

您可以通过指定镜像属性的元数据类型来执行此操作,并仅用于归因。

[MetadataType(typeof(Dinner_Validation))] 
public partial class Dinner 
{} 

public class Dinner_Validation 
{ 
    [Required] 
    public string Title { get; set; } 
}

史蒂夫史密斯在博客上发表了here

不幸的是,上述方法对于重构来说是脆弱的。另一种选择是使用新的POCO实体。就我所知,这些完全避免了编译时代码生成。我还没有使用它们,所以不能评论任何陷阱或权衡。

答案 1 :(得分:12)

您可以使用Designer将其添加到EDMX文件中:

<Property Name="Nome" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" >
            <Documentation>
              <Summary>[MyCustomAttribute]</Summary>
            </Documentation>
</Property>

并取代T4:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

使用:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    if(edmProperty.Documentation != null && string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false)
    {
    #>
    <#=edmProperty.Documentation.Summary#>
<#+
    }
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

答案 2 :(得分:8)

您可以在界面上创建界面和声明属性。

partial class Person : IPerson {}

public interface IPerson
{
    [Required]
    string Name { get; set; }
}

答案 3 :(得分:3)

您可以使用Designer将其添加到EDMX文件中:

<Property Name="Nome" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" >
            <Documentation>
              <Summary>[MyCustomAttribute]</Summary>
            </Documentation>
</Property>

并取代T4:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

使用:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty)
{
    if(edmProperty.Documentation != null && string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false)
    {
    #>
    <#=edmProperty.Documentation.Summary#>
<#+
    }
    WriteProperty(Accessibility.ForProperty(edmProperty),
                  code.Escape(edmProperty.TypeUsage),
                  code.Escape(edmProperty),
                  code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
                  code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

对于Entity Framework 6,替换

public string Property(EdmProperty edmProperty)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        "{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)));
}

public string Property(EdmProperty edmProperty)
{
    var description = String.Empty;
    bool isAttribute = false;

    if(edmProperty.Documentation != null &&
        string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false)
    {
        string summary = edmProperty.Documentation.Summary;
        if (!String.IsNullOrEmpty(summary) && summary.First() == '[' && summary.Last() == ']')
        {
            isAttribute = true;
        }

        if (isAttribute)
        {
            description = String.Format("\r\n\t{0}\r\n\t", summary);
        }
        else
        {
            description = String.Format("\r\n\t/// <summary>\r\n\t/// {0}\r\n\t/// </summary>\r\n\t", 
                summary);
        }

    }

    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)),
        description);
}

警告:

  • 绝对需要彻底解决命名空间。
  • 假设属性以'['开头并以']结尾' - 没有其他错误检查
  • 如果未找到开始和结束括号,则实体框架属性摘要将包含在XML三次斜杠注释中。
  • 尝试匹配默认的visual studio样式信息(实际上只是缩进),这可能是您的项目的情况,也可能不是。这包括新行。

示例输出:

/// <summary>
/// content type
/// </summary>
public System.Guid ContentType { get; set; }

[System.ComponentModel.DisplayName("Last Modified")]
public System.DateTime LastModified { get; set; }

答案 4 :(得分:0)

我不相信你可以。生成器将所有类声明为部分允许您扩展它,但它不允许您使用自定义属性标记属性,因为它将简单地生成它们。您可以做的一件事就是编写自己的实体。

答案 5 :(得分:0)

除了BurnsBA的回复,要将其应用于导航属性,也请更新NavigationProperty()

public string NavigationProperty(NavigationProperty navProp)
{
    var description = String.Empty;
    if(navProp.Documentation != null && string.IsNullOrWhiteSpace(navProp.Documentation.Summary) == false)
    {
        string summary = navProp.Documentation.Summary;
        if (!String.IsNullOrEmpty(summary) && summary.First() == '[' && summary.Last() == ']')
        {
            description = String.Format("\r\n\t{0}\r\n\t", summary);
        }
        else
        {
            description = String.Format("\r\n\t/// <summary>\r\n\t/// {0}\r\n\t/// </summary>\r\n\t", summary);
        }
    }

    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)),
        description);
}

我使用此功能将[Newtonsoft.Json.JsonIgnore]添加到我的媒体资源中。

注意:您必须将这些内容添加到<...>Model.tt而不是<...>Model.Context.tt