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

当我在表单(视图)中将 FirstName 或 IsRequired() 的其他字段留空时,验证不会启动。它只是遇到错误:

一个或多个实体的验证失败。有关更多详细信息,请参阅“EntityValidationErrors”属性。

不幸的是,这个错误并没有说太多。我挖得更深了,但我唯一能得到的是

列名鉴别器无效。

我认为这将是某处被遗忘的继承(对于 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 事实上,上面的属性是这个问题的一个可能的解决方案。

4

3 回答 3

4

仅当您使用“数据注释”时才开始验证 - 而 HasRequired 执行映射 - 数据注释属性同时执行映射和验证部分。
即为了验证您的观点,我相信您必须在您的属性上放置注释/属性。

这通常用于在“映射”与映射和验证之间“区分”。即,如果您希望两者都使用属性,如果您只想映射使用流畅的配置。

这里也有一个相关的答案https://stackoverflow.com/a/9310435/417747https://stackoverflow.com/a/9789984/417747

编辑:这更接近你所需要的,感谢贾斯汀
如何使流利的 API 配置与 MVC 客户端验证一起工作?

于 2012-04-06T18:38:25.373 回答
4

我认为您将 EF 模型验证与 MVC 验证混淆了。MVC 对 EF 一无所知,反之亦然。它们是独立的技术,可以很好地协同工作。

当您在流式数据模型上定义验证时,您只是在为实体框架定义验证。这显然有效,因为当您尝试保存更改时,EF 失败并抱怨验证失败。

同样,这与 MVC 验证无关,并且两者在大多数情况下不能一起工作(一个例外是,如果您使用 POCO 类并使用 Data 注释,则某些注释在 MVC 和 EF 中都有效,但有些不这样做。直接在视图中使用数据模型不是一个好习惯,所以这在很大程度上是一个有争议的问题。)

于 2012-04-06T18:59:09.760 回答
1

你说的都是对的,我的假设是错误的。

[必需] 不等同于 .IsRequired()

有几种可能的解决方案:

1)快速简单属性

模型配置覆盖和验证

使用 CodeFirst,可以覆盖使用验证属性定义的模型配置,例如在 OnModelCreating 方法中。重新配置模型会影响验证,因为验证应该使用实际的模型配置——盲目使用属性会导致验证错误,因为根据 OnModelCreating() 中的覆盖,这些值可能是有效的。以下是在 OnModelCreating 中进行覆盖的三种特殊情况:

  • 如果一个属性用 [Required] 属性修饰并被重新配置为可选(.IsOptional() 方法),则 [Required] 属性将被删除并因此在验证发生时被忽略

  • 如果属性用 [StringLength] 或 [MaxLength] 属性修饰,然后配置了新长度(.HasMaxLength() 方法),如果可能,将使用新的最大长度

  • 如果用 [StringLength] 或 [MaxLength] 属性修饰属性,然后将其定义为允许的最大长度 (.IsMaxLength),则将删除该属性(如果可能)并且不会检查属性值的长度

请注意,上述更改仅在使用某些验证属性修饰的属性时才有效。因此,根据需要设置属性 (.IsRequired()) 不会导致针对空值验证属性。
请参阅EF 功能 CTP5:验证

2)一个快速修复,但它是一个肮脏的,因为神秘人建议
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) The heavy one: The Validation Application Block in Enterprise Library
http://bradwilson.typepad.com/blog/2009/10/enterprise-library-validation-example-for-aspnet-mvc-2.html but Enterprise Library is very often considered as an overkill

4) Validation nirvana: FluentValidation looks very promising and I'll definitely give it a try.
http://www.nuget.org/packages/FluentValidation.MVC3
Cons: Not the best approach in an n-layer app. It's primarily focused on Views.

5) N-Layer
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
This approach leads to problems with a validation on the client side so it must be solved separately.

于 2012-04-06T19:29:56.353 回答