Ошибка Entity Framework при отправке пустых полей
-
21-09-2019 - |
Вопрос
VS 2010 Бета-версия 2, .NET 4.
В моем приложении ASP.NET MVC 2, когда я отправляю форму методу action, который принимает объект, созданный entity framework, я получаю следующую ошибку:
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" и имеет тип "text NOT NULL" в MS SQL 2008.
Мое действие проверит, является ли значение nullorempty , если это так, будет добавлена ошибка модели, но я получаю ошибку, как только отправляю форму.
Решение
Привязываетесь ли вы непосредственно к объекту?Конечно, похоже на то.Итак, у вас есть два варианта:
- Напишите пользовательскую привязку модели, которая преобразует null -> пустую строку.
- Привяжитесь к модели редактирования, которая вместо этого допускает значения null, а затем измените это значение на пустую строку при копировании значений в объект в действии.
Лично я бы выбрал № 2.Я думаю, вы всегда должны использовать модели просмотра / редактирования, и это отличный пример того, почему.
Другие советы
У меня была та же проблема.Я осмотрелся и нашел работу где-то здесь.В нем описывается проблема, вызванная проверкой EF, выполняемой до проверки требуемого поля.Это также показывает, как мы можем обойти эту проблему, используя [DisplayFormat]
Пометка.Надеюсь, это поможет вам.
Вот ссылка на вопрос и обходной путь:
Проверка на стороне сервера ТРЕБУЕМОГО строкового свойства в MVC2 Entity Framework 4 не работает
Является ли это проблемой с MVC2 и Entity Framework 4 или это сделано специально?Похоже, что проверка свойств EF отлично работает для полей datetime, не обнуляемых (обязательных), а проверка типов данных числовых и строковых полей работает без необходимости использования ViewModels.
Я воссоздал проблему с помощью простой таблицы FOOBAR, используя один столбец varchar (50) с ненулевым значением под названием barName в slq 2008.Я сгенерировал модель EF из этой базы данных и быстро добавил контроллер и созданное представление для объекта FOOBAR.Если я попытаюсь опубликовать действие 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; }
}
}
}
Ответ Ашиша Шакьи помог мне.Я добавил этот атрибут к свойству, и теперь оно работает.
[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();
}
}
Импортируйте пространство имен:
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.
У меня была такая же проблема, и я исправил ее, сделав false
Для true
вот так:
Line 4502:
_Text = StructuralObject.SetValidValue(value, false);
У меня самого просто была такая же проблема, и я пришел сюда, чтобы найти решение.Однако ответ может быть улучшен.
Svavar's и HackITMngr были на правильном пути, однако объединение обоих дает наилучший результат.Вы не хотите украшать сгенерированные классы, так как рискуете потерять свои пользовательские изменения при внесении изменений в модель EF.
[MetadataType(typeof(MyTableMetaData))] общедоступный частичный класс MyTable { // Правила проверки для класса Album
public class MyTableMetaData
{
[DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
public string MyTextProperty { get; set; }
}
}
Чтобы уладить любые споры между ними.Я бы сказал, что Svavar был прямым ответом, HackITMngr был улучшением.
У меня отлично работает!
Я установил свойство StoreGeneratedPattern как вычисляемое для каждого поля, и это решило проблему для меня.