ADO.NET Entities Framework Рекомендации по производительности, которые должен знать каждый разработчик

Каковы рекомендации по производительности, которые должен знать каждый разработчик ADO.NET EF?

Пожалуйста, поместите каждый совет на каждый ответ и объясните, почему отзыв хорош (например, минимизируя округление DB).

Ответ 1

Используйте ObjectContext#GetObjectByKey() для извлечения объектов по их ключу вместо использования оператора First() (или FirstOrDefault) в запросе LINQ. Последний будет попадать в базу данных каждый раз, в то время как первый сначала будет искать кеш EF (ObjectStateManager для конкретной) для объекта и не будет попадать в базу данных, если найден объект с указанным ключом.

Ссылки

Ответ 2

То, что я только что узнал при профилировании SQL, сгенерированных кодом EF, используемым в моем приложении: есть разница между:

IEnumerable<User> users = DB.User.Where(...);
int count = users.Count();

и

IQueryable<User> users = DB.User.Where(...);
int count = users.Count();

Первый генерирует полный запрос для извлечения сопоставленных строк из таблицы User, и подсчет выполняется после того, как данные были возвращены в EF. Последний делает то, что обычно ожидается: сгенерируйте SELECT COUNT ... SQL, который намного эффективнее.

Это довольно тонко, но не сложно понять, почему, заметив об этом: это связано с статически связанной природой метода расширения С#.

Небольшой способ обойти это - использовать ключевое слово "var" для объявления переменной:

var users = DB.users.Where(...);
int count = users.Count();

Это приведет к объявлению "пользователей" как того же типа, который возвращает ".Where"; который является IQueryable < > .

Ответ 3

Предположим, что BlogPost сущность ссылается на объект User через свойство Author. Вместо указания полного объекта User на свойство BlogPost.Author (для которого может потребоваться обращение к базе данных), инициализируя ссылку правильной EntityKey. Например:

BlogPost.AuthorReference.EntityKey = new EntityKey("EFNamespace.User", "Id", userId);

Ответ 4

Быстрый и простой способ обновления отдельных объектов объекта. Это метод расширения.

public static void AttachUpdated(this ObjectContext obj, EntityObject objectDetached)
{
    if (objectDetached.EntityState == EntityState.Detached)
    {
        object original;
        if (obj.TryGetObjectByKey(objectDetached.EntityKey, out original))
            obj.ApplyPropertyChanges(objectDetached.EntityKey.EntitySetName, objectDetached);
        else
            throw new ObjectNotFoundException();
    }
}