Ошибка Entity Framework при отправке пустых полей
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();
Свойство называется "Текст" и имеет тип "текст НЕ ПУСТО" в MS SQL 2008.
Мое действие проверит, является ли значение nullorempty, если это так, будет добавлена ошибка модели, но я получаю ошибку, как только я отправляю форму.
8 ответов
Связываете ли вы непосредственно с сущностью? Конечно, похоже на это. Итак, у вас есть два варианта:
- Напишите пользовательский связыватель модели, который переводит нуль -> пустую строку.
- Привязать к редактируемой модели, которая вместо этого допускает пустые значения, а затем изменить ее на пустую строку при копировании значений в сущность в действии.
Я бы выбрал № 2 лично. Я думаю, что вы всегда должны использовать модели просмотра / редактирования, и это отличный пример того, почему.
У меня была такая же проблема. Я оглянулся вокруг и нашел здесь работу. Это описывает проблему как вызванную проверкой EF, имеющей место перед проверкой обязательного поля. Это также показывает, как мы можем обойти эту проблему, используя [DisplayFormat]
Тег. Надеюсь, что это поможет вам.
Вот ссылка на вопрос и обходной путь:
Проверка на стороне сервера НЕОБХОДИМОГО свойства строки в MVC2 Entity Framework 4 не работает
У меня была такая же проблема, и я решил ее false
в true
как это:
Line 4502:
_Text = StructuralObject.SetValidValue(value, false);
Это проблема с MVC2 и Entity Framework 4 или это задумано? Похоже, что проверка свойств EF работает нормально для полей типа datetime (не обязательных) (обязательных), а проверка типов данных числовых и строковых полей работает без необходимости использования ViewModels.
Я воссоздал проблему, используя простую таблицу FOOBAR, используя единственный столбец varchar(50), не имеющий значения null, называемый barName, в slq 2008. Я сгенерировал модель EF из этой базы данных и быстро добавил контроллер и представление CREATE для сущности FOOBAR. Если я пытаюсь POST выполнить действие CREATE, не вводя значение для свойства barName, VS переходит в исключение в файле designer.cs модели (как и в предыдущем примере). Когда я пытаюсь пройти мимо исключения, в форме появляется сообщение проверки, и поле выделяется розовым цветом.
Кажется, что-то идет не в правильной последовательности. Потому что исключение происходит до того, как VS перейдет в метод HTTPPOST CREATE.
Я нашел код из примера ASP.Net MvcMusicStore полезным. http://mvcmusicstore.codeplex.com/releases/view/44445
Похоже, что привязка к 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, показывает сообщение об ошибке при проверке и не завершится ошибкой на сервере с нулевым значением.
Я установил свойство StoreGeneratedPattern как вычисляемое для каждого поля, и это решило проблему для меня.
У меня была такая же проблема, и я пришел сюда, чтобы найти решение. Тем не менее, ответ может быть расширен.
Svavar и HackITMngr были на правильном пути, однако объединение обоих дает лучший результат. Вы не хотите украшать сгенерированные классы, так как рискуете потерять свои пользовательские изменения при модификации модели EF.
[MetadataType (typeof (MyTableMetaData))] публичный частичный класс MyTable { // Правила проверки для класса Album
public class MyTableMetaData
{
[DisplayFormat(ConvertEmptyStringToNull = false, NullDisplayText="")]
public string MyTextProperty { get; set; }
}
}
Чтобы уладить любые споры между двумя. Я бы сказал, что Svavar был прямым ответом, HackITMngr был улучшением.
Прекрасно работает для меня!