Code First Fluent API 验证不起作用

4

有一个类 - 它是一个普通的类,没有什么特别之处:

public class Trader{

public Guid UserId {get;set;}
public int TraderId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Skype { get; set; }
public string Photo { get; set; }
public string Email { get; set; }

public virtual User User { get; set; }
}

映射:

 public TraderMap()
        {
            this.ToTable("Trader", "General");
            this.HasKey(a => a.TraderId);
            this.HasRequired(a => a.User).WithMany().HasForeignKey(a => a.UserId);
            Property(a => a.UserId).HasColumnName("UserID").IsRequired();
            Property(a => a.TraderId).HasColumnName("TraderID").IsRequired();

            Property(a => a.FirstName).HasMaxLength(50).IsRequired();
            Property(a => a.LastName).HasMaxLength(50).IsRequired();
            Property(a => a.PhoneNumber).HasMaxLength(25).IsRequired();
            Property(a => a.Skype).HasMaxLength(50).IsOptional();
            Property(a => a.Photo).HasMaxLength(100).IsOptional();
            Property(a => a.Email).HasMaxLength(100).IsRequired();
        }

当我在表单 (View) 中留空 FirstName 或其他需要 IsRequired() 的字段时,验证不会触发。它只会遇到以下错误:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
不幸的是,这个错误并没有太多的提示信息。我深入挖掘了一下,但我唯一能得到的东西是:
Invalid column name discriminator.
我以为这可能与 User 类中的某些遗忘的继承有关,但我没有找到任何可疑的东西。
问题在于当我在 Trader 类中使用属性时,一切都按预期工作。
   public class Trader{

    public Guid UserId {get;set;}
    public int TraderId { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [Required]
    public string PhoneNumber { get; set; }
    public string Skype { get; set; }
    public string Photo { get; set; }
    [Required]
    public string Email { get; set; }

    public virtual User User { get; set; }
    }

有了属性,验证工作正常,@Html.ValidationMessageFor开始显示错误消息,并且不允许发送NULL值。

你有什么建议,我的映射存在什么问题吗?

更新1 实际上,上面的属性是解决此问题的一种可能方案。


你能发布你的用户类和映射吗? - Justin Pihony
1
我不明白。当您尝试插入空格时,错误是“验证失败”,因此验证确实正常工作。 - Erik Funkenbusch
基于Fluent API配置抛出的验证错误不会自动到达UI,但您可以在代码中捕获它,然后根据需要做出响应。 - CAD bloke
3个回答

4
只有使用“数据注释”时,验证才会启动 - 而HasRequired执行映射 - 数据注释属性同时执行映射和验证部分。
例如,为了使您的视图验证,我认为您必须在属性上放置注释/属性。这通常用于区分仅“映射”和映射和验证两者之间的差异。如果您需要两者都使用属性,如果只需要映射,则使用流畅配置。
此处也有相关答案或此处
编辑:由于Justin的帮助,这个更接近您需要的
如何使流畅API配置与MVC客户端侧验证一起工作?

4
我认为你混淆了EF模型验证和MVC验证。MVC对EF一无所知,反之亦然。它们是分离的技术,可以很好地协同工作。
当你在流畅的数据模型上定义验证时,你只是为Entity Framework定义验证。这显然是有效的,因为当你尝试保存更改时,EF会失败并抱怨验证失败。
再次强调,这与MVC验证无关,两者大多数情况下不能协同工作(一个例外是,如果你使用POCO类并使用数据注释,则某些注释在MVC和EF中都起作用,但某些不起作用。直接在视图中使用数据模型不是好习惯,因此这在很大程度上是一个无意义的观点)。

2
你们两个都是对的,我有错误的假设。 [Required]并不等同于.IsRequired()
有几种可能的解决方案:
1)快速简单属性 模型配置覆盖和验证
使用 CodeFirst,可以在 OnModelCreating 方法中覆盖使用验证属性定义的模型配置。重新配置模型会影响验证,因为验证应该使用实际的模型配置,而盲目地使用属性会导致针对某些值进行验证错误,这些值在 OnModelCreating() 中进行了覆盖并且可能是有效的。以下是在 OnModelCreating 中进行的三个特殊情况的覆盖:
- 如果属性以 [Required] 属性装饰,并被重新配置为可选 (.IsOptional() 方法),那么 [Required] 属性将被删除,因此在发生验证时将被忽略。 - 如果属性以 [StringLength] 或 [MaxLength] 属性装饰,然后通过新的长度配置 (.HasMaxLength() 方法) 进行配置,则将使用新的最大长度(如果可能)。 - 如果属性以 [StringLength] 或 [MaxLength] 属性装饰,然后定义为允许最大长度 (.IsMaxLength),则该属性将被删除(如果可能),并且不会检查属性值的长度。
请注意,上述更改仅在某些验证属性装饰的属性上有效。因此,将属性设置为必需的 (.IsRequired()) 不会导致针对 null 值进行属性验证。 有关详细信息,请参见 EF Feature CTP5: Validation。
2) 一个快速的解决方法,但正如Mystere Man所建议的那样,它是一个肮脏的方法。
http://thedatafarm.com/blog/data-access/capturing-code-first-fluent-api-validationresults-to-display-in-mvc3-views/

http://bradwilson.typepad.com/blog/2010/10/service-location-pt6-model-validation.html

3) 重的那个: 企业库中的验证应用程序块,但企业库经常被认为是过度设计。
4) 验证境界FluentValidation 看起来非常有前途,我一定会试试。
http://www.nuget.org/packages/FluentValidation.MVC3
缺点:在 n 层应用程序中并不是最佳方法。它主要关注视图。
5) N层架构
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
这种方法会导致客户端验证出现问题,因此必须单独解决。

那不是解决方案,那只是一种权宜之计。使用异常处理预期(且常见)的情况是非常糟糕的做法。异常就像其名称所示,是例外情况。也就是说,它们只应在发生未计划的事情时才会出现。这是处理问题的非常糟糕的选择。 - Erik Funkenbusch
嗯,它很好地回答了我的问题,并且在讨论中有一个链接指向Brad Wilson的博客http://bradwilson.typepad.com/blog/2010/10/service-location-pt6-model-validation.html,这是一个不错的起点。 - nubm

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