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

18

在使用Database First方法生成模型时,我们希望避免在下一次从数据库生成模型时覆盖更改,因此需要使用MetadataTypeAttribute为模型添加验证

我注意到有些人即使使用Code First方法并且没有机会被某种自动生成的代码覆盖他们的实体类,仍然使用MetadataType定义验证。

即使使用Code First方法定义实体模型,也有意义将这些DataAnnotations分离到部分类定义中,然后使用MetadataType进行链接,而不是直接在实体类上应用这些DataAnnotations吗?

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;}
}
4个回答

17
这些DataAnnotations被应用于实际的Entity类本身是否有意义?即使使用Code First方法定义实体模型,分离这些属性到局部类定义中,然后使用MetadataType链接,是否更为合适?
在大多数情况下,这样做是没有意义的,因为它涉及不必要和冗余的代码复制,仅仅是为了将一些属性与属性相关联。
如果实体类模型是由您编写的代码创建的,则没有意义。
如果它是使用您可以控制的某些自定义代码生成器(如T4模板)创建的,则也没有意义,因为您可以自定义生成器本身。
唯一有意义的情况是当您无法控制实体类代码时(例如,来自第三方库的类)。在这种情况下,您可以使用AssociatedMetadataTypeTypeDescriptionProvider类将元数据与第三方类相关联。
例如,假设以下类来自另一个没有源代码的库:
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 配置中的元数据类来获取 organizationId,以使用适当的注释类。 :) - Bimal Das

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

0

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

首先,你有数据验证

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

模型验证

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


我现在感觉我的问题可能不够清晰。请查看更新的描述。 - sachin

0

我不知道为什么你要使用数据库优先技术来实现更完整的,比如说代码优先,因为你可以创建ViewModel来满足你的目的。此外,并非所有的数据注释都受到Entity Framework的支持。

MetadataType的限制

  1. 它不能应用于属性,只能应用于每个类类型的单个类。
  2. 此属性不能被继承,因此您无法自定义它。
  3. 另一方面,此属性可以应用于部分类,这是此属性的主要目的。
  4. 此属性将受到ASP.NET MVC的尊重,但不会被Entity Framework读取。

使用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
@sachin 我在这方面进行了很多探索,但是没有官方的使用方法或示例来展示如何与codefirst一起工作。有些人在他们的code first项目中成功地利用了这种DB first技术,但其中一些人遇到了验证问题。我认为这可能是一种hack,并且在某种程度上取决于你的编程方式。因此,你必须在你的情况下进行测试。 - Amirhossein Mehrvarzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接