Entity Framework 4.1, код во-первых, при сохранении ссылка на ленивую загрузку пуста - PullRequest
4 голосов
/ 21 сентября 2011

Я создаю проект форума для ASP.NET MVC 3, работающего в .NET 4 с последней версией Entity Framework.

У меня обычный дизайн форума с доской с категориями иКатегории с форумами, форумы с темами и темы с сообщениями и т. Д.

Упрощено:

public class Category {
    [Required]
    public virtual Board Board { get; set; }
}
public class Forum {
    [Required]
    public virtual Category Category { get; set; }
}
public class Topic {
    [Required]
    public virtual Forum Forum { get; set; }
}
public class Post {
    [Required]
    public virtual Topic Topic { get; set; }
}

При создании нового сообщения сообщается тема, а при изменении темы - форум.

Итак, снова упростили:

public class Forum {
    public void TopicChanged(Topic topic) {
        // Do stuff
    }
}
public class Topic {
    public void PostAdded(Post post) {
        // Do stuff
        this.Forum.TopicChanged(this);
    }
}

Итак, после создания нового сообщения (и фиксации его в базе данных) я вызываю PostAdded в родительской теме.Теперь это становится странным!

Когда я фиксирую изменения в своих репозиториях, я получаю ошибку проверки, требуется Категория на форуме.

Если я смотрю в базе данных, форумимеет ссылку на родительскую категорию.Если я остановлю код и посмотрю на объект Forum, у него будет экземпляр Category.Так что это похоже на проблему с отложенной загрузкой, особенно потому, что если я добавлю эту строку:

var cat = this.Category

В нижней части метода TopicChanged в классе Forum больше не будет ошибок.

Я делаю что-то совершенно не так, столкнулся с пограничной проблемой или что происходит?Я подумал, что EF увидит, что ссылка является загруженной ссылкой с отложенной загрузкой, и если она не была изменена, нет причины, по которой это должно завершиться неудачей при сохранении ???

Спасибо, Стин

1 Ответ

8 голосов
/ 22 сентября 2011

Я исправил свою проблему. Возможно, это не очень хорошее и чистое решение, но, по крайней мере, сейчас я могу справиться с этой ситуацией, не меняя много моего кода (который также должен работать с nHibernate). Так что грязного решения нет.

Просто чтобы дать вам представление о том, как это решить, я попытаюсь объяснить это здесь.

В методе Commit () моего репозитория я начинаю с вызова метода GetValidationErrors () для экземпляра DbContext. Это возвращает ошибку, с которой я столкнулся выше, вместе с сущностью, где произошла ошибка В базовом типе этой сущности (это прокси-сервер, сгенерированный EF), я запускаю все свойства, и когда я сталкиваюсь со свойством с атрибутом Required, я вызываю GetValue для идентичного свойства прокси-объекта.

Хватит разговоров, больше кодов:

var errors = this.context.GetValidationErrors();
foreach (DbEntityValidationResult result in errors) {
    Type baseType = result.Entry.Entity.GetType().BaseType;
    foreach (PropertyInfo property in result.Entry.Entity.GetType().GetProperties()) {
        if (baseType.GetProperty(property.Name).GetCustomAttributes(typeof(RequiredAttribute), true).Any()) {
            property.GetValue(result.Entry.Entity, null);
        }
    }
}
...