Добавить аннотации данных к классу, сгенерированному инфраструктурой сущности
У меня есть следующий класс, сгенерированный каркасом сущности:
public partial class ItemRequest
{
public int RequestId { get; set; }
//...
Я хотел бы сделать это обязательным полем
[Required]
public int RequestId { get;set; }
Однако, поскольку это сгенерированный код, он будет уничтожен. Я не могу представить способ создания частичного класса, потому что свойство определяется порожденным частичным классом. Как я могу определить ограничение безопасным способом?
Ответы
Ответ 1
Сгенерированный класс ItemRequest
всегда будет классом partial
. Это позволяет вам написать второй частичный класс, который отмечен необходимыми аннотациями данных. В вашем случае частичный класс ItemRequest
будет выглядеть следующим образом:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
//make sure the namespace is equal to the other partial class ItemRequest
namespace MvcApplication1.Models
{
[MetadataType(typeof(ItemRequestMetaData))]
public partial class ItemRequest
{
}
public class ItemRequestMetaData
{
[Required]
public int RequestId {get;set;}
//...
}
}
Ответ 2
В ответ на MUG4N вы можете использовать частичные классы, но лучше использовать интерфейсы. В этом случае вы будете иметь ошибки компиляции, если модель EF не соответствует модели проверки. Таким образом, вы можете модифицировать свои модели EF, не опасаясь, что правила проверки устарели.
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace YourApplication.Models
{
public interface IEntityMetadata
{
[Required]
Int32 Id { get; set; }
}
[MetadataType(typeof(IEntityMetadata))]
public partial class Entity : IEntityMetadata
{
/* Id property has already existed in the mapped class */
}
}
P.S. Если вы используете тип проекта, который отличается от ASP.NET MVC (при выполнении ручной проверки данных), не забудьте зарегистрировать валидаторы
/* Global.asax or similar */
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity));
Ответ 3
Я нашел решение вроде ответа MUG4N, но вместо этого вложил класс MetaData
в класс сущности, тем самым уменьшив количество классов в вашем публичном списке имен и устранив необходимость иметь уникальное имя для каждого класса метаданных.
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models
{
[MetadataType(typeof(ItemRequest.MetaData))]
public partial class ItemRequest
{
internal class MetaData
{
[Required]
public int RequestId {get;set;}
//...
}
}
}
Обязательно поместите "." в функции typeof
.
Ответ 4
Это своего рода расширение для ответа @dimonser, если вы регенерируете свою модель db, вам придется вручную повторно добавлять интерфейсы в эти классы.
Если у вас есть живот, вы также можете изменить свои шаблоны .tt
:
Здесь пример автогенерирующих интерфейсов для некоторых классов, это фрагмент из .tt
, просто замените метод EntityClassOpening
в вашем следующем (и, очевидно, var stringsToMatch
с именами и интерфейсами сущностей).
public string EntityClassOpening(EntityType entity)
{
var stringsToMatch = new Dictionary<string,string> { { "Answer", "IJourneyAnswer" }, { "Fee", "ILegalFee" } };
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}{4}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)),
stringsToMatch.Any(o => _code.Escape(entity).Contains(o.Key)) ? " : " + stringsToMatch.Single(o => _code.Escape(entity).Contains(o.Key)).Value : string.Empty);
}
Ни один нормальный человек не должен делать это сам с собой, хотя в Библии было доказано, что для этого идет ад.
Ответ 5
Я не уверен, как делать то, о чем вы просите, но есть способ обойти это. Динамическая проверка данных путем переопределения GetValidators вашего пользовательского DataAnnotationsModelValidatorProvider. В нем вы можете прочитать правила для проверки каждого поля (из базы данных, файла конфигурации и т.д.) И, при необходимости, добавить валидаторы. Он имеет добавленные значения, что ваша проверка более не тесно связана с моделью и может быть изменена без необходимости даже перезапуска сайта. Конечно, это может быть излишним для вашего дела, но это было идеально для наших!
Ответ 6
Измените шаблон T4, добавив требуемые аннотации, этот файл обычно называется MODELNAME.tt
найдите, где T4 создает класс и методы, чтобы знать, куда их поместить.
<#=codeStringGenerator.IgnoreJson(navigationProperty)#>
//create this method in file
public string IgnoreJson(NavigationProperty navigationProperty){
string result = navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? "" : @"[JsonIgnore]
[IgnoreDataMember]";
return result;
}
Вам также нужно будет добавить пространства имен;
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Runtime.Serialization;
Восстановите свои классы, сохранив свою модель, все ваши методы должны быть аннотированы.