在Code First的情况下,使用MetadataType强制执行验证是否有意义?

sac*_*hin 13 .net c# validation asp.net-mvc entity-framework

我似乎理解在数据库优先的情况下帮助MetadataTypeAttribute模型添加验证背后的原因,因为我们希望避免在下次从数据库生成模型时覆盖的更改.

我注意到很少有人MetadataType使用Code First方法定义验证,并且他们的实体类不可能被某种自动生成的代码覆盖.

将这些DataAnnotations直接应用于实际的Entity类是否有意义,而是将它们分成部分类定义,然后使用链接MetadataType,即使使用Code First方法定义实体模型?

public class MyEntity
{
    [Required]
    public string Name { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

VS

public partial class MyEntity
{
    public string Name { get; set;}
}

[MetadataType(typeof(MyEntityMetadata))]
public partial class MyEntity
{
}

public class MyEntityMetadata
{
    [Required]
    public string Name { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

Iva*_*oev 11

将这些DataAnnotations直接应用于实际的Entity类是否有意义,而是将它们分离为部分类定义,然后使用MetadataType进行链接,即使使用Code First方法定义实体模型也是如此?

在大多数情况下,它没有意义,因为它涉及不必要和冗余的代码重复,只是为了将一些属性与属性相关联.

如果您使用代码创建实体类模型则没有意义.

如果它是通过一些您可以控制的自定义代码生成(如T4模板)创建的,那也没有意义,因为您可以自定义生成本身.

有意义的唯一情况是当您无法控制实体类代码时(例如,来自第三方库的类).在这种情况下,您可以使用AssociatedMetadataTypeTypeDescriptionProvider类将元数据与第三方类关联.

例如,假设以下类来自另一个没有源代码的库:

public sealed class ExternalEntity
{
    public string Name { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以定义元数据类:

public class ExternalEntityMetadata
{
    [Required]
    public string Name { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

并将它与ExternalEntityusing TypeDescriptor.AddProvider方法关联一次(在应用程序启动期间或其他事情):

TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(
    typeof(ExternalEntity), typeof(ExternalEntityMetadata),
    typeof(ExternalEntity));
Run Code Online (Sandbox Code Playgroud)