【问题标题】:Entity Framework error when submitting empty fields提交空字段时出现实体框架错误
【发布时间】:2010-12-19 04:01:04
【问题描述】:

VS 2010 Beta 2,.NET 4。

在我的 ASP.NET MVC 2 应用程序中,当我将表单提交给接受由实体框架创建的对象的操作方法时,我收到以下错误:

Exception Details: System.Data.ConstraintException: This property cannot be set to a  
null value.

Source Error: 


Line 4500:                OnTextChanging(value);
Line 4501:                ReportPropertyChanging("Text");
Line 4502:                _Text = StructuralObject.SetValidValue(value, false);
Line 4503:                ReportPropertyChanged("Text");
Line 4504:                OnTextChanged();

该属性名为“Text”,在 MS SQL 2008 中属于“text NOT NULL”类型。

我的操作将检查该值是否为空或空,如果是,则会添加模型错误,但我一提交表单就会收到错误。

【问题讨论】:

  • 也许这与您的问题没有直接关系,但不推荐使用 TEXT 数据类型。从 SQL Server 2005 开始,您就有了 NVARCHAR(MAX)。它在许多情况下都更容易使用。
  • 谢谢,我将字段更改为 nvarchar(并使用实体框架更新向导更新了数据库模型),但问题仍然存在。

标签: asp.net-mvc-2 .net-4.0 .net-4.0-beta-2


【解决方案1】:

您是否直接绑定到实体?确实看起来像。所以你有两个选择:

  1. 编写一个自定义模型绑定器,它可以转换 null -> 空字符串。
  2. 绑定到允许空值的编辑模型,然后在将值复制到操作中的实体时将其更改为空字符串。

我个人会选择#2。我认为您应该始终使用查看/编辑模型,这是一个很好的例子。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。我环顾四周,发现这里有一个工作。它将问题描述为由在必填字段验证之前进行的 EF 验证引起的。它还展示了我们如何通过使用[DisplayFormat] 标签来解决这个问题。希望这会对你有所帮助。

    这是问题和解决方法的链接:

    Server-side validation of a REQUIRED String Property in MVC2 Entity Framework 4 does not work

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题并通过将false 设置为true 来解决它,如下所示:

      Line 4502:
      _Text = StructuralObject.SetValidValue(value, false);
      

      【讨论】:

        【解决方案4】:

        这是 MVC2 和 Entity Framework 4 的问题还是设计使然?似乎 EF 属性验证适用于日期时间不可为空(必需)字段,并且数字与字符串字段的数据类型验证无需使用 ViewModel 即可正常工作。

        我在 slq 2008 中使用一个名为 barName 的单一、不可为空的 varchar(50) 列使用简单的 FOOBAR 表重新创建了问题。我从该数据库生成了 EF 模型,并快速添加了一个控制器和一个 CREATE 视图FOOBAR 实体。如果我尝试 POST 到 CREATE 操作而不输入属性 barName 的值,VS 会进入模型的 Designer.cs 文件中的异常(就像上面的那个)。当我尝试跳过异常时,验证消息显示在表单上,​​并且该字段以粉红色突出显示。

        似乎某些东西没有按正确的顺序触发。因为异常发生在VS进入HTTPPOST CREATE方法之前。

        我发现 ASP.Net MvcMusicStore 示例中的代码很有帮助。 http://mvcmusicstore.codeplex.com/releases/view/44445#DownloadId=119336

        看来绑定到 ViewModel 解决了这个问题。

        namespace MvcMusicStore.ViewModels
        {
            public class StoreManagerViewModel
            {
                public Album Album { get; set; }
                public List<Artist> Artists { get; set; }
                public List<Genre> Genres { get; set; }
            }
        }
        ........
        
        namespace MvcMusicStore.Models
        {
            [MetadataType(typeof(AlbumMetaData))]
            public partial class Album
            {
                // Validation rules for the Album class
        
                [Bind(Exclude = "AlbumId")]
                public class AlbumMetaData
                {
                    [ScaffoldColumn(false)]
                    public object AlbumId { get; set; }
        
                    [DisplayName("Genre")]
                    public object GenreId { get; set; }
        
                    [DisplayName("Artist")]
                    public object ArtistId { get; set; }
        
                    [Required(ErrorMessage = "An Album Title is required")]
                    [StringLength(160)]
                    public object Title { get; set; }
        
                    [DisplayName("Album Art URL")]
                    [StringLength(1024)]
                    public object AlbumArtUrl { get; set; }
        
                    [Required(ErrorMessage = "Price is required")]
                    [Range(0.01, 100.00, ErrorMessage="Price must be between 0.01 and 100.00")]
                    public object Price { get; set; }
                }
            }
        }
        

        【讨论】:

          【解决方案5】:

          Ashish Shakya 的回答帮助了我。我将此属性添加到属性中,现在它可以工作了。

          [DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
          

          所以它看起来像这样:

              [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
              [DataMemberAttribute()]
              [DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
              public global::System.String MyProperty
              {
                  get
                  {
                      return _MyProperty;
                  }
                  set
                  {
                      OnMyPropertyChanging(value);
                      ReportPropertyChanging("MyProperty");
                      _MyProperty = StructuralObject.SetValidValue(value, false);
                      ReportPropertyChanged("MyProperty");
                      OnMyPropertyChanged();
                  }
              }
          

          【讨论】:

            【解决方案6】:

            导入命名空间:

            using System.ComponentModel.DataAnnotations;
            

            并添加属性属性[Required]

            [Required]
            public global::System.String MyProperty
                {
                    get
                    {
                        return _MyProperty;
                    }
                    set
                    {
                        OnMyPropertyChanging(value);
                        ReportPropertyChanging("MyProperty");
                        _MyProperty = StructuralObject.SetValidValue(value, false);
                        ReportPropertyChanged("MyProperty");
                        OnMyPropertyChanged();
                    }
                }
            

            因此 ModelState.IsValid 等于 false,在验证中显示错误消息并且不会在服务器上以 Null 失败。

            【讨论】:

              【解决方案7】:

              我自己也遇到了同样的问题,来这里寻找解决方案。但是,答案可以得到加强。

              Svavar's 和 HackITMngr 走在正确的轨道上,但是将两者结合起来会产生最佳结果。您不想去装饰生成的类,因为在修改 EF 模型时您可能会丢失自定义更改。

              [元数据类型(typeof(MyTableMetaData))] 公共部分类 MyTable { // Album 类的验证规则

                  public class MyTableMetaData
                  {
                      [DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
                      public string MyTextProperty { get; set; }
                  }
              }
              

              解决两者之间的任何争论。我会说 Svavar 是直接答案,HackITMngr 是增强。

              非常适合我!

              【讨论】:

                【解决方案8】:

                我为每个字段将 StoreGeneratedPattern 属性设置为 Computed,它为我解决了问题。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-07-03
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多