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

问题描述:

是否有任何方法将自定义属性添加到EF生成代码中的属性?我能看到的唯一合理的解决方案是创建一个定制的T4模板。但是,由于属性的性质,不可能为每个EF属性确定正确的属性参数。在Entity Framework代码中添加自定义属性属性

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

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

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

史蒂夫史密斯博客关于它here

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

+0

我刚刚爱上了EF,当我突然意识到我的实体的属性由于处理方式而实际上不存在。 GRRRR。 – Chev 2010-11-23 07:17:47

+4

当反映时,`assembly.GetType(typeof(Dinner).ToString()。GetProperties()`,`property.Attributes`为null并且`property.GetCustomAttributes(typeof(RequiredAttribute))`返回一个零长度的数组 - 应该一个反映Dinner_Validation或是其他东西是错误的? – lukiffer 2011-06-24 23:13:36

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

+0

这可能是如此,但也有几个选项现在。查看我的答案获取信息。 – 2010-08-18 21:01:52

您可以在接口上创建接口和声明属性。

partial class Person : IPerson {} 

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

作为未来读者的一个便笺,这不会*与asp.net-mvc的验证工作 – 2014-03-17 22:29:35

你也可以将它添加到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))); 
} 

您可以添加此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))); 
} 

而对于实体框架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三重斜杠注释中。
  • 尝试匹配默认的视觉工作室样式信息(实际上只是缩进),这可能或可能不是您的项目的情况。这包括新行。

输出样本:

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

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

除了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