Добавление пользовательских атрибутов свойств в код Entity Framework

StackOverflow https://stackoverflow.com/questions/1050714

Вопрос

Есть ли какой-нибудь способ добавить пользовательские атрибуты к свойствам в сгенерированном EF коде?Единственное, что я вижу в качестве правдоподобного решения, - это создать пользовательский шаблон T4.Однако из-за природы атрибута было бы невозможно определить правильный параметр атрибута для каждого свойства EF.

Это было полезно?

Решение

Вы можете сделать это, указав тип метаданных, который отражает свойства и используется просто для атрибуции.

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

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

Стив Смит ведет блог об этом здесь.

К сожалению, описанный выше подход является хрупким для рефакторинга.Другой вариант - использовать новые объекты POCO.Насколько я могу судить, они полностью избегают генерации кода во время компиляции.Я еще не использовал их, поэтому не могу комментировать какие-либо подводные камни или компромиссы.

Другие советы

Вы также можете добавить это в 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)));
}

Вы можете создать интерфейс и объявить атрибут в интерфейсе.

partial class Person : IPerson {}

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

Вы также можете добавить это в 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);
}

Предупреждения:

  • Пространства имен должны быть разрешены абсолютно.
  • Предполагается, что атрибуты начинаются с '[' и заканчиваются на ']' - никакой другой проверки ошибок
  • Если открывающая и закрывающая фигурные скобки не найдены, сводка свойств entity framework помещается в XML-комментарий с тройной косой чертой.
  • Пытается сопоставить информацию о стиле Visual Studio по умолчанию (на самом деле просто отступы), которая может быть, а может и не быть, применима к вашему проекту.Это включает в себя новые строки.

пример вывода:

/// <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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top