2015-04-15 2 views
23

У меня есть структура Entity Framework, и она отлично работает большую часть времени, в которой я нуждаюсь. У меня есть такая структураEntity Framework - Stop Lazy Загрузка похожих объектов по запросу?

public partial class Topic : Entity 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public DateTime CreateDate { get; set; } 
    public virtual Post LastPost { get; set; } 
    public virtual Category Category { get; set; } 
    public virtual IList<Post> Posts { get; set; } 
    public virtual IList<TopicTag> Tags { get; set; } 
    public virtual MembershipUser User { get; set; } 
    public virtual IList<TopicNotification> TopicNotifications { get; set; } 
    public virtual IList<Favourite> Favourites { get; set; } 
    public virtual Poll Poll { get; set; } 
} 

Как вы можете видеть, у меня есть ряд связанных объектов, которые являются списками. Они отображаются в стандартном и ленивы загружены, так что я могу назвать Topic.Posts или Topic.TopicNotifications и т.д. ... (Mappings ниже)

HasOptional(t => t.LastPost).WithOptionalDependent().Map(m => m.MapKey("Post_Id")); 
HasOptional(t => t.Poll).WithOptionalDependent().Map(m => m.MapKey("Poll_Id"));    
HasRequired(t => t.Category).WithMany(t => t.Topics).Map(m => m.MapKey("Category_Id")); 
HasRequired(t => t.User).WithMany(t => t.Topics).Map(m => m.MapKey("MembershipUser_Id")); 
HasMany(x => x.Posts).WithRequired(x => x.Topic).Map(x => x.MapKey("Topic_Id")).WillCascadeOnDelete(); 
HasMany(x => x.TopicNotifications).WithRequired(x => x.Topic).Map(x => x.MapKey("Topic_Id")).WillCascadeOnDelete(); 
HasMany(t => t.Tags) 
    .WithMany(t => t.Topics) 
    .Map(m => 
       { 
        m.ToTable("Topic_Tag"); 
        m.MapLeftKey("TopicTag_Id"); 
        m.MapRightKey("Topic_Id"); 
       }); 

Это все хорошо. Но в некоторых случаях мне нужно вручную заполнять темы. Пост и тема.

Но если я пытаюсь установить Topic.Posts = SomeCollection он запускает ленивую нагрузку и загружает все посты, а затем позволяет мне установить мою коллекцию так что я получаю два набора SQL выполненного (первый я не хочу)

Есть ли вообще, отключить ленивую загрузку вручную по требованию только тогда, когда я хочу установить коллекцию вручную?

Надежда, что имеет смысл ...:/

+5

Я чувствую проблему XY здесь http://meta.stackexchange.com/a/66378/134199 - Я думаю, что ваша РЕАЛЬНАЯ проблема - это «необходимость вручную заполнять темы. Вероятно, вы пытаетесь сделать что-то, что намного лучше сделано по-другому, поскольку то, что вы делаете, не имеет никакого смысла. Что именно вы пытаетесь сделать ... и почему? –

+1

Я буду второй, что говорит @ErikFunkenbusch. Зачем вам нужно вручную создавать коллекцию «Сообщения» и «Избранное»? –

+0

Если вы ответите на то, что вы пытаетесь сделать, мы, возможно, действительно сможем помочь вам решить вашу реальную проблему .. нет проблемы, которую вы ДУМАЕТЕСЬ, потому что вы ДУМАЕТЕ, что вам нужно сделать что-то конкретное, чтобы решить вашу проблему проблема. –

ответ

3

Поскольку вы используете отложенную загрузку, вы должны иметь прокси для ваших классов и свойств коллекции.

Замена этих свойств коллекции прокси на свои собственные коллекции кажется для меня довольно странным дизайном. Вы теряете отслеживание изменений и, скорее всего, получаете пару других странных побочных эффектов.

Я бы рекомендовал либо использовать прокси/ленивую загрузку, либо отказаться от идеи замены коллекций, либо отступить от использования прокси и получить полный контроль над сгенерированными классами POCO.

Какой из двух подходов подходит наилучшим образом для ваших нужд, зависит от вашего общего использования структуры сущности.

12

Мне не известно о подходе, нацеленном на этот точный сценарий, поэтому мне нужно будет временно отключить/включить ленивую загрузку.

using(var context = new MyContext()) 
{ 
    context.Configuration.LazyLoadingEnabled = false; 
    // do your thing using .Include() or .Load() 
    context.Configuration.LazyLoadingEnabled = true; 
} 

Однако обратите внимание, что это глобальная конфигурация, так что может быть проблемой параллелизм, если это произойдет в вашем сценарии.

+1

Я бы возражал против такого подхода, поскольку вы больше не можете гарантировать наличие включенного объекта в объектах сущности, поэтому вам нужно будет убедиться, что вы всегда проверяете нулевые записи, прежде чем пытаться получить доступ к включенным объектам. Переключение Lazy Loading и Proxies во время выполнения может иметь множество неожиданных последствий и сделать отладку головной болью. – AllMadHare

+2

@AllMadHare: Я согласен. Ваше решение намного лучше. –

+1

@JeroenVannevel Это не глобальная собственность .. по крайней мере, не в EF 6. Я предполагаю, что есть способ установить его глобально, и этот конфиг, вероятно, клонирован из стандартного/глобального, но Configuration (и этот флаг) являются свойствами экземпляра , –

21

Лучше отключить ленивую загрузку по умолчанию и вместо этого указать, когда вы хотите загрузить дополнительные данные в первую очередь. EF настроен таким образом, чтобы позволить загрузку Eager с помощью функции .Include() в вашем запросе, при ленивой загрузке она может стать беспорядочной, если вы начнете включать/выключать ее для различных функций, вам лучше просто отключить ее и управлять что/когда вы хотите, чтобы данные загружались, если вы чувствуете необходимость отключить их.

Для получения конкретных примеров см. https://msdn.microsoft.com/en-nz/data/jj574232.aspx, а также разбивку различных способов загрузки/ленивой загрузки данных. Первый пример показывает, как вы могли бы удалять сообщения из блога, что похоже на то, что вы хотите добиться.

var topics = context.Topics 
         .Include(t => t.Posts) 
         .ToList(); 
8

Я бы не стал рекомендовать отключить загрузку для отдыха в зависимости от запроса. Как предлагает AllMadHare, вы можете полностью отключить ленивую загрузку, но это может повлиять на то, как вы загружаете все данные.Я бы рекомендовал удаление виртуального ключевого слова из сообщений так, что ваш класс выглядит следующим образом:

public partial class Topic : Entity 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public DateTime CreateDate { get; set; } 
    public virtual Post LastPost { get; set; } 
    public virtual Category Category { get; set; } 
    public IList<Post> Posts { get; set; } 
    public virtual IList<TopicTag> Tags { get; set; } 
    public virtual MembershipUser User { get; set; } 
    public virtual IList<TopicNotification> TopicNotifications { get; set; } 
    public virtual IList<Favourite> Favourites { get; set; } 
    public virtual Poll Poll { get; set; } 
} 

За документации найти здесь: https://msdn.microsoft.com/en-us/data/jj574232.aspx#lazyOffProperty это позволит вам ленивой нагрузке всех остальных свойствам навигации и сообщениям нетерпеливых нагрузок, если вам нужно ,

Смежные вопросы