Подтвердить что ты не робот

Запрос объектов после AddObject перед SaveChanges?

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

Спасибо

4b9b3361

Ответ 1

вы можете запросить объекты, подобные этому,

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

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

GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged)

Ответ 2

Чтобы сохранить сущность, вы обычно добавляете ее в контекст 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.

Ответ 3

В 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;
    }
}