У меня есть следующий класс, созданный структурой сущностей:
public partial class ItemRequest
{
public int RequestId { get; set; }
//...
Я хочу сделать это поле обязательным
[Required]
public int RequestId { get;set; }
Однако, поскольку это сгенерированный код, он будет уничтожен. Я не могу представить себе способ создать частичный класс, потому что свойство определяется сгенерированным частичным классом. Как я могу определить ограничение безопасным способом?
c#
entity-framework
asp.net-mvc-4
П.Брайан Макки
источник
источник
Ответы:
Сгенерированный класс
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;} //... } }
источник
Как ответил 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 */ } }
PS Если вы используете тип проекта, который отличается от ASP.NET MVC (когда вы выполняете ручную проверку данных), не забудьте зарегистрировать свои валидаторы
/* Global.asax or similar */ TypeDescriptor.AddProviderTransparent( new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity));
источник
Я нашел такое решение, как ответ MUG4N , но вместо этого вложил
MetaData
класс в класс сущности, тем самым уменьшив количество классов в вашем списке общедоступных пространств имен и устранив необходимость иметь уникальное имя для каждого класса метаданных.using System.ComponentModel.DataAnnotations; namespace MvcApplication1.Models { [MetadataType(typeof(MetaData))] public partial class ItemRequest { public class MetaData { [Required] public int RequestId; //... } } }
источник
[NotMapped]
внутри частичного класса, когда они мне нужны.Это своего рода расширение ответа @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); }
Ни один нормальный человек не должен поступать так с собой, ведь в Библии доказано, что за это человек попадает в ад.
источник
Я не уверен, как сделать то, о чем вы просите, но есть способ обойти это. Динамическая проверка данных путем переопределения GetValidators вашего настраиваемого DataAnnotationsModelValidatorProvider. В нем вы можете прочитать правила проверки каждого поля (из базы данных, файла конфигурации и т. Д.) И при необходимости добавить валидаторы. Он имеет дополнительные преимущества в том, что ваша проверка больше не тесно связана с моделью и может быть изменена без необходимости даже перезапуска сайта. Конечно, для вашего случая это было бы излишним, но для нашего он был идеальным!
источник
Измените шаблон 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;
Восстановите свои классы, сохранив вашу модель, все ваши методы должны быть аннотированы.
источник