#asp.net-mvc #asp.net-mvc-3 #data-annotations #ef-code-first #entity-framework-4.1
#asp.net-mvc #asp.net-mvc-3 #данные-аннотации #ef-code-first #entity-framework-4.1
Вопрос:
У меня есть Comment
класс, обладающий, среди прочего, Author
свойством:
public class Comment : IEquatable<Comment>
{
public int ID { get; set; }
[Required]
public virtual User Author { get; set; }
// More properties here
}
Я хочу, чтобы пользователи могли ставить «лайк» комментарию, как здесь, в StackOverflow. С этой целью у меня есть следующее действие в моем CommentController
:
public virtual ActionResult Like(int id)
{
var comment = _session.Single<Comment>(c => c.ID == id);
comment.Likes ;
_session.CommitChanges();
return Json(new { comment.Likes });
}
Всякий раз, когда я вызываю это действие, я получаю следующую ошибку проверки:
Требуется поле Author.
Comment
Объект поступает из базы данных, поэтому у него есть автор. «Забавно» то, что всякий раз, когда я использую отладчик Visual Studio, чтобы проверить, действительно ли Author
отсутствует, ошибка проверки не выдается.
Прав ли я, предполагая здесь, что проблема заключается в том, что отложенная загрузка Author
свойства никогда не выполняется? Если да, то как я могу, только для этой ситуации, принудительно заполнить все свойства навигации? (В противном случае я хочу продолжать работать с отложенной загрузкой)
Какой самый аккуратный способ решить это? Я вообще на правильном пути? И почему не происходит отложенной загрузки, в то время как EF явно требует сохранения объекта?
Мы будем признательны за любую помощь.
Комментарии:
1. Несколько необычно помещать
Required
в поле, не являющееся строкой. В документации говорится , что»Исключение проверки возникает, если свойство имеет значение null, содержит пустую строку («») или содержит только символы пробела».2. @Hightechrider — Сначала я использую код, и одна из вещей,
RequiredAttribute
которые он делает, — это пометить отношение FK какON DELETE CASCADE
, чего я и хотел здесь. И MSDN говорит об этомRequiredAttribute
: «Указывает, что значение поля данных является обязательным». . Это не только для строк, AFAIK.
Ответ №1:
Вы могли бы использовать Include
для быстрого извлечения отношения в контексте данных.
context.Comments.Include("Author").Single<Comment>(c => c.ID == id);
Комментарии:
1. Спасибо @Darin — Есть ли какой-либо другой способ? Это вынудило бы меня «выйти» из моей реализации Unit of Work и использовать
context
непосредственно в моем действии, чего я бы предпочел не делать. Теперь все это так красиво абстрагировано и слабо связано …![]()
2. Я полагаю, я всегда мог бы добавить
EagerSingle<T>()
метод в свойISession
интерфейс.3. @Sergi Papaseit, вы могли бы использовать уровень сервиса, инкапсулирующий эту логику и предоставляющий
Like(int commentId)
метод. В обязанности контроллера не входит выполнение таких действий, как извлечение комментариев,Likes
обновление. Все, что для этого нужно, это вызвать соответствующий метод service.4. @Darin — Не будет ли это излишеством в данной ситуации? Для этого действия не так много кода, и нет ничего, чего «действительно не должно там быть», не так ли?
5. @Sergi Papaseit, контроллеры не должны быть жирными. Посадите их на диету .
Ответ №2:
У меня была похожая проблема. Приведенное ниже должно работать (с включенной ленивой загрузкой).
public virtual ActionResult Like(int id)
{
var comment = _session.Single<Comment>(c => c.ID == id);
comment.Likes ;
if(TryUpdateModel(comment))
{
_session.CommitChanges();
}
return Json(new { comment.Likes });
}
Комментарии:
1. Я пробовал, и это действительно работает. Хотя это кажется хакерским. Это скорее обходной путь, чем решение, не так ли?
2. Насколько я понимаю, оно «объединяет» исходный объект с измененной версией (это, очевидно, упрощено). Так что я не вижу в этом особого хака. Лично я считаю, что это лучше, чем отключать ленивую загрузку или создавать любые другие сложные обходные пути.