在EntityFramework中,可以在调用SaveChanges方法之前查询刚刚使用AddObject添加到上下文中的对象吗?
由于
答案 0 :(得分:27)
要保留实体,通常会在上下文中将其添加到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
似乎没有意识到要更改,直到它们持续存在于db。
幸运的是,每个DbSet
都有Local
属性,其作用类似于DbSet
本身,但它反映了所有内存中的操作
var howMany = context.Bars.Local.Count(b => b.Name == "foo");
// howMany == 1
您还可以使用Local
添加实体
context.Bars.Local.Add(bar);
并摆脱Entity Framework的奇怪行为。
答案 1 :(得分:10)
你可以查询这样的对象,
context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(obj => obj.Entity).OfType<TheEntityType>()
这将查询处于添加状态的对象。如果你也想要其他状态,你可以将所有其他状态传递给GetObjectStateEntries
这样的方法。
GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged)
答案 2 :(得分:1)
在休眠中,瞬态实例已经附加到上下文中。偶然发现了这个EF限制。
我没有设法将ObjectSet
与其瞬态实体ObjectSet.Local
相交/联合,但对于我们的用例,下面的find方法就足够了。
在我们的例子中,我们根据迭代期间的唯一标准创建一些实体惰性
查找方法
如果您使用的是存储库模式,则可以创建一个方法:
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;
}
}