【问题标题】:Does it make sense to use MetadataType to enforce validations in case of Code First?在 Code First 的情况下使用 MetadataType 强制验证是否有意义?
【发布时间】:2023-03-24 04:30:02
【问题描述】:

我似乎明白了在Database First 的情况下求助MetadataTypeAttributeAdd Validation to the Model 背后的原因,因为我们希望避免下次从数据库生成模型时更改被覆盖。

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

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

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

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

【问题讨论】:

    标签: c# .net asp.net-mvc entity-framework validation


    【解决方案1】:

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

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

    如果实体类模型是你用代码创建的就没意义了。

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

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

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

    public sealed class ExternalEntity
    {
        public string Name { get; set;}
    }
    

    然后就可以定义元数据类了:

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

    并使用TypeDescriptor.AddProvider 方法将其与ExternalEntity 关联一次(在应用程序启动或其他情况下):

    TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(
        typeof(ExternalEntity), typeof(ExternalEntityMetadata),
        typeof(ExternalEntity));
    

    【讨论】:

    • 哇!终于得到了解决方案。非常感谢。实际上,我试图为来自同一视图模型的不同组织实现不同的注释。现在我可以使用 web config 中的元数据类来获取 organizationId 以使用适当的注释类。 :)
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      所以首先你有数据验证

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

      模型验证

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

      【讨论】:

      • 我现在感觉可能是我的问题不够清楚。请查看更新后的说明。
      【解决方案4】:

      我不知道您为什么要尝试使用数据库优先技术来实现更完整的技术,例如代码优先,因为您可以创建 ViewModel 来满足您的目的。实体框架也并不支持所有数据注释。

      元数据类型限制

      1. 它不能应用于属性,只能应用于 每个班级类型都有一个班级。
      2. 该属性不能被继承,所以不能自定义。
      3. 另一方面,该属性可以应用于部分类 这是该属性的主要用途。
      4. ASP.NET MVC 将尊重此属性,但不会被读取 通过实体框架。

      使用 MetadataType 的缺点

      • 您必须使用ViewBagViewData 或其他方式才能通过 视图的附加信息
      • 您的设计不太可测试,因为它依赖于静态对象 机制。
      • 它也不是必需的,有人可以省略它而不会破坏 任何东西。
      • 这也意味着您将模型类拆分为 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;}
      }
      

      【讨论】:

      • 感谢您的回答。但是在 CodeFirst 的情况下使用您在答案中发布的代码是否有意义?这就是我的问题所在。
      • @sachin 我对此进行了很多探索,但没有官方使用或示例表明它与 codefirst 一起工作。有些人在他们的代码优先项目中成功地利用了这种数据库优先技术,其中一些人遇到了验证问题。 我认为这可能是 hack,在某种程度上取决于你的编程方式。 所以你必须在你的情况下测试它
      猜你喜欢
      • 1970-01-01
      • 2011-11-22
      • 2017-11-17
      • 2012-05-09
      • 1970-01-01
      • 2015-12-29
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      相关资源
      最近更新 更多