Коллекция Entity Framework 4.1 со ссылками на производительность влияет? - PullRequest
2 голосов
/ 10 октября 2011

Я запускаю сценарии тестирования, чтобы решить, следует ли внедрять систему с использованием Entity Framework, и натолкнулся на интересный вопрос.У меня есть коллекция объектов «PersonCollectable», хранящихся в «Person», и каждый «PersonCollectable» ссылается на «страницу»;Извлечение коллекции предоставляет мне все объекты PersonCollectable, которые я хочу отобразить, но я также хочу отобразить имя страницы. Приведет ли это к запросу для каждой страницы и, таким образом, отрицательно повлияет на производительность?

public class Person
{
    public virtual ICollection<PersonCollectable> Collection { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }    
}

public class PersonCollectable
{
    public int Id { get; set; }
    public virtual Page Page { get; set; }
    public int PageId { get; set; }
}

public class Page
{
    public int Id { get; set; }
    public string Name { get; set; }
}

И это тестовый код для извлечения информации и отображения результатов.Представьте, что коллекция заполнена не менее чем 500 элементами, поэтому это может привести к 500 дополнительным запросам на каждый веб-запрос.Машина разработки может справиться с этим, но я хотел бы знать, не приведет ли это к разрушению опубликованного продукта.

Person example = db.People.Single( s => s.Name == "Roel" );
foreach( PersonCollectable exampleCollectable in example.Collection ) {
    Console.WriteLine( "{0} rated {1}", exampleCollectable.Page.Name, exampleCollectable.Rating );
}

Пожалуйста, поделитесь своим мнением и помогите мне ответить на этот вопрос, приведет ли это кзапрос для каждой страницы и таким образом отрицательно влияет на производительность? Спасибо.

1 Ответ

4 голосов
/ 10 октября 2011

Да, это приведет к 500 запросам, потому что ваш способ загрузки свойств навигации основан на отложенной загрузке (virtual свойства навигации).

Если вы хотите загрузить весь граф объекта за один шаг /туда и обратно в БД вы должны EF сказать, что, используя Include при выполнении запроса:

Person example = db.People
    .Include(s => s.Collection.Select(c => c.Page))
    .Single(s => s.Name == "Roel");

(оставшийся код может остаться без изменений.)

В вашем конкретном случае рекомендуетсяМожно использовать проекцию, что означает, что вы загружаете только те свойства, которые вам нужны:

var example = db.People
    .Where(s => s.Name == "Roel")
    .Select(s => new
    {
        PersonName = s.Name,
        CollectedData = s.Collection.Select(c => new
        {
            PageName = c.Page.Name,
            Rating = c.Rating
        })
    })
    .Single();

Console.WriteLine( "Person {0}:", example.PersonName);
foreach(var item in example.CollectedData)
{
    Console.WriteLine( "{0} rated {1}", item.PageName, item.Rating );
}

Вместо использования анонимного типа вы также можете создать собственный тип с именем «View» и проецировать в него с помощьюSelect(s => new MyViewType...) и т. Д.

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