Добавить аннотации данных в класс, созданный структурой сущности

У меня есть следующий класс, созданный структурой сущности:

public partial class ItemRequest
{
    public int RequestId { get; set; }
    //...

Я хотел бы сделать это обязательным полем

[Required]
public int RequestId { get;set; }

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

7 ответов

Решение

Сгенерированный класс 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;

            //...
        }
    }
}

Это своего рода расширение ответа @dimonser. Если вы регенерируете свою модель БД, вам придется вручную заново добавить интерфейсы для этих классов.

Если у вас есть желудок для этого, вы также можете изменить свой .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;

Восстановите ваши классы, сохранив вашу модель, все ваши методы должны быть аннотированы.

Это решение, работающее с контроллером. Я имею в виду ModelState.Isvalid Проверить мою проверку в представлении. Но я не могу проанализировать свою форму в javascript jquery.validate.unobtrusive.min.js для переключения проверки на стороне клиента перед отправкой формы в контроллер. работает с ViewModel, но я не могу использовать с моделью edmx

Другие вопросы по тегам