C# 在代码优先的情况下,使用MetadataType强制执行验证有意义吗?

C# 在代码优先的情况下,使用MetadataType强制执行验证有意义吗?,c#,.net,asp.net-mvc,entity-framework,validation,C#,.net,Asp.net Mvc,Entity Framework,Validation,我似乎理解了在我们希望避免在下次从数据库生成模型时覆盖更改的情况下使用MetadataTypeAttribute的原因 我注意到很少有人使用MetadataType定义验证,即使他们使用这种方法,他们的实体类也不可能被某种自动生成的代码覆盖 不直接将这些数据注释应用于实际的实体类,而是将它们分离为部分类定义,然后使用MetadataType链接,即使使用方法定义实体模型,这有什么意义吗 public class MyEntity { [Required] public strin

我似乎理解了在我们希望避免在下次从数据库生成模型时覆盖更改的情况下使用
MetadataTypeAttribute
的原因

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

不直接将这些数据注释应用于实际的实体类,而是将它们分离为部分类定义,然后使用
MetadataType
链接,即使使用方法定义实体模型,这有什么意义吗

public class MyEntity
{
    [Required]
    public string Name { get; set;}
}
vs


我不知道为什么您要尝试使用数据库优先技术来实现更完整的,比如说,代码优先,因为您可以创建ViewModels来满足您的目的。此外,并非所有的数据注释都在实体框架中受支持

元数据类型限制
  • 它不能应用于属性,只能应用于 每个类类型对应一个类
  • 无法继承此属性,因此无法对其进行自定义
  • 另一方面,该属性可以应用于分部类 这是该属性的主要目的
  • ASP.NET MVC将遵守此属性,但不会读取该属性 按实体框架
  • 使用MetadataType的缺点
    • 您必须使用
      ViewBag
      ViewData
      或其他方法才能传递 视图的附加信息
    • 您的设计不太容易测试,因为它依赖于静态对象 机制
    • 它也不是必需的,有人可以省略它而不破坏它 什么都行
    • 这还意味着您正在将模型类拆分为3个文件。 一个是生成的,一个是您的,另一个是具有属性的
    如果要将属性添加到类中的现有属性(部分):

    这可能有效,也可能被EF忽略,测试它:

    public partial class YourModelClass
    {
        public string YourProperty{get;set;}
    }
    
    //Your Partial Class
    [MetadataType(typeof(YourModelClassMetaData))]
    public partial class YourModelClass
    {
    }
    
    //The class that adds your attributes
    public class YourModelClassMetaData
    {
        [Required]
        public object YourProperty{get;set;}
    }
    

    创建一个类并多次使用它是很有意义的。在代码优先的方法中,您需要数据验证,这可以通过使用数据注释来实现,并且当您有许多具有相同特性的道具时,这样做会使您的生活更加轻松。这不仅仅是关于覆盖,在这种情况下还有其他一些原因。希望能很好地理解您的问题,我的回答是恰当的。

    我认为问题在于模型上的数据注释和代码上的数据注释的区别在哪里

    所以首先要进行数据验证

    这是在代码优先模型上设置属性 这将设置数据库列的配置,这将设置数据模型的大小和限制。(如果不迁移数据,此项一旦填充通常不会更改。)

    模型验证

    模型验证是将表单绑定到的模型。 此模型将包含有关UI的更多信息

    即使使用代码优先的方法定义实体模型,也不要直接将这些数据注释应用于实际的实体类,而是将它们分离为部分类定义,然后使用MetadataType链接,这样做有意义吗

    public class MyEntity
    {
        [Required]
        public string Name { get; set;}
    }
    
    在大多数情况下,这是没有意义的,因为它涉及到不必要的和冗余的代码复制,只是为了将一些属性和属性关联起来

    如果实体类模型是由您使用代码创建的,这是没有意义的

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

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

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

    public sealed class ExternalEntity
    {
        public string Name { get; set;}
    }
    
    然后可以定义元数据类:

    public class ExternalEntityMetadata
    {
        [Required]
        public string Name { get; set;}
    }
    
    并使用方法将其与
    ExternalEntity
    关联一次(在应用程序启动或其他过程中):


    谢谢你的回答。但是在CodeFirst的情况下,使用您在答案中发布的代码有意义吗?这就是我的问题所在。@sachin我在这方面做了很多探索,但是没有官方的应用程序或示例显示它与codefirst一起工作。有些人在他们的代码优先项目中成功地利用了这种DB-first技术,有些人在验证方面遇到了麻烦。我认为这可能是黑客行为,在某种程度上取决于你的编程方式。所以你必须在你的案例中测试它,我现在感觉可能是我的问题不够清楚。请查看更新的描述。哇!终于找到了解决办法。谢谢。实际上,我试图从同一个viewmodel为不同的组织实现不同的注释。现在,我可以使用web配置中的元数据类来获取organizationId以使用适当的注释类。:)
    TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(
        typeof(ExternalEntity), typeof(ExternalEntityMetadata),
        typeof(ExternalEntity));