programing tip

엔티티 프레임 워크에서 생성 된 클래스에 데이터 주석 추가

itbloger 2020. 9. 3. 07:56
반응형

엔티티 프레임 워크에서 생성 된 클래스에 데이터 주석 추가


엔터티 프레임 워크에서 생성 한 다음 클래스가 있습니다.

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

이 필드를 필수 필드로 만들고 싶습니다.

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

그러나 이것은 생성 된 코드이기 때문에 지워질 것입니다. 속성이 생성 된 부분 클래스에 의해 정의되기 때문에 부분 클래스를 만드는 방법을 상상할 수 없습니다. 안전한 방식으로 제약 조건을 어떻게 정의 할 수 있습니까?


생성 된 클래스 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;

            //...
        }
    }
}

This is sort of extension to @dimonser answer if you regenerate your db model you will have to manually re-add interfaces on those classes.

If you have stomach for it you can also modify your .tt templates:

Here's example of auto-generating interfaces on some classes, this is fragment from .tt just replace EntityClassOpening method in yours with following (and obviously var stringsToMatch with your entity names and interfaces).

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);
}

No normal person should do this to himself though, it has been proven in Bible that one goes to Hell for this.


I am not sure how to do what you are asking for but there is a way around it. Dynamic data validation by overriding the GetValidators of your custom DataAnnotationsModelValidatorProvider. In it you can read the rules for validating each field (from a database, config file, etc.) and add validators as need be. It has the added values that your validation is no longer tightly coupled to the model and can be changed without need to even restart the site. Of course it might be overkill for your case, but it was ideal for ours!


Modify the T4 template adding required annotations, this file is usually named MODELNAME.tt

find where the T4 is creating the class and methods to know where to put these.

     <#=codeStringGenerator.IgnoreJson(navigationProperty)#>


//create this method in file
public string IgnoreJson(NavigationProperty navigationProperty){
            string result = navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? "" : @"[JsonIgnore]
    [IgnoreDataMember]";

            return result;
        }

You will also need to add the namespaces;

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Runtime.Serialization;

Rebuild your classes by saving your model, all your methods should be annotated.

참고URL : https://stackoverflow.com/questions/16736494/add-data-annotations-to-a-class-generated-by-entity-framework

반응형