Запрашивать объекты после AddObject перед SaveChanges? - PullRequest
15 голосов
/ 09 августа 2011

В EntityFramework возможно ли запросить объекты, которые были только что добавлены в контекст, с помощью AddObject, но перед вызовом метода SaveChanges?

Спасибо

Ответы [ 3 ]

27 голосов
/ 12 декабря 2011

Чтобы сохранить сущность, вы обычно добавляете ее к DbSet в контексте.

Например

var bar = new Bar();
bar.Name = "foo";
var context = new Context();
context.Bars.Add(bar);

Удивительно, но при запросе context.Bars только что добавленная сущность не может быть найдена

var howMany = context.Bars.Count(b => b.Name == "foo");
// howMany == 0

После context.SaveChanges() та же строка приведет к 1

Кажется, что DbSet не знает изменений, пока они не сохранятся в БД.

К счастью, каждый DbSet обладает свойством Local, которое действует как сам DbSet, но отражает все операции в памяти

var howMany = context.Bars.Local.Count(b => b.Name == "foo");
// howMany == 1

Вы также можете использовать Local для добавления сущностей

context.Bars.Local.Add(bar);

и избавьтесь от странного поведения Entity Framework.

10 голосов
/ 09 августа 2011

Вы можете запросить объекты, как это,

context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(obj => obj.Entity).OfType<TheEntityType>()

это запросит объекты, которые находятся в добавленном состоянии. Если вам нужны и другие состояния, вы можете передать все остальные состояния методу GetObjectStateEntries следующим образом.

GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged)
1 голос
/ 05 февраля 2016

В переходных режимах hibernate уже привязаны к контексту.Просто наткнулся на это ограничение EF.

Мне не удалось пересечь / объединить ObjectSet с его переходными объектами ObjectSet.Local, но для нашего сценария использования достаточно метода ниже:

В наших случаях мы создаем некоторые объекты, ленивые в зависимости от уникальных критериев во время итерации

Метод поиска

Если вы используете шаблон репозитория, вы можете создатьметод как:

public interface IRepository<T> where T : class, IEntity
{
    /// <summary>
    /// Finds the unique Entity with the given predicate.
    /// Depending on implementation also checks transient / local (unsaved) Entities.
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    IQueryable<T> FindAll(Expression<Func<T, bool>> predicate);
}

public class EfRepository<T> : IRepository<T> where T : class, IEntity
{
    protected readonly ObjectContext context;
    protected readonly ObjectSet<T> objectSet;

    /// <summary>
    /// Creates a new repository of the given context.
    /// </summary>
    /// <param name="context"></param>
    public EfRepository(ObjectContext context)
    {
        if (context == null)
            throw new ArgumentException("Context must not be null.");
        this.context = context;
        this.objectSet = context.CreateObjectSet<T>();
    }

    /// <summary>
    /// Also takes local context into consideration for unsaved changes
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public T Find(Expression<Func<T, bool>> predicate)
    {
        T result = this.objectSet.Where(predicate).FirstOrDefault();
        if (result == null)
            result = this.objectSet.Local().Where(predicate).FirstOrDefault();
        return result;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...