Есть ли способ добавить пользовательские атрибуты к свойствам в сгенерированном EF-коде? Единственное, что я вижу в качестве правдоподобного решения, - это создать собственный шаблон T4. Однако из-за природы атрибута невозможно определить правильный параметр атрибута для свойства EF.
Добавление атрибутов пользовательского свойства в код Entity Framework
Ответ 1
Вы можете сделать это, указав тип метаданных, который отражает свойства и используется просто для атрибуции.
[MetadataType(typeof(Dinner_Validation))]
public partial class Dinner
{}
public class Dinner_Validation
{
[Required]
public string Title { get; set; }
}
Стив Смит пишет об этом здесь.
К сожалению, вышеупомянутый подход является хрупким для рефакторинга. Другим вариантом является использование новых объектов POCO. Насколько мне известно, они избегают генерации кода во время компиляции. Я еще не использовал их, поэтому не могу комментировать любые подводные камни или компромиссы.
Ответ 2
Вы можете добавить это в файл 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)));
}
Ответ 3
Вы можете создать интерфейс и объявить атрибут на интерфейсе.
partial class Person : IPerson {}
public interface IPerson
{
[Required]
string Name { get; set; }
}
Ответ 4
Вы можете добавить это в файл 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.
- Попытка сопоставить стандартную визуальную визуальную студийную информацию (действительно просто отступы), которая может быть или не быть в случае вашего проекта. Это включает в себя новые строки.
вывод образца:
/// <summary>
/// content type
/// </summary>
public System.Guid ContentType { get; set; }
[System.ComponentModel.DisplayName("Last Modified")]
public System.DateTime LastModified { get; set; }
Ответ 5
Я не верю, что ты можешь. Генератор объявляет все классы как частичные, позволяя вам расширять его, но он не позволит вам отмечать свойства с помощью настраиваемых атрибутов, поскольку он просто генерирует их. Единственное, что вы можете сделать, это написать свои собственные объекты.
Ответ 6
В дополнение к сообщению 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