Entity Framework ObjectContext是否正确实现了工作单元模式?

时间:2010-06-25 14:24:41

标签: entity-framework entity-framework-4

实体框架4 - STE - 具有单表博客的简单数据库具有BlogID PK列...

var samplesDbEntities = new SamplesDBEntities();
var blogId = Guid.NewGuid();
samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId });
var objectSetResult = samplesDbEntities.Blogs
                                       .Where(p => p.BlogID == blogId)
                                       .SingleOrDefault();

(代码执行的结果=> objectSetResult ==在最后一行之后为null)

AFAIK,ObjectContext是UoW模式的实现,在这种情况下,我想我应该从ObjectSet(Repository)返回结果只是“标记为瞬态” 有人可以解释一下我做错了什么以及为什么objectSetResult在这里有空值?

(是的,我知道ObjectStateManager,但对我而言,它更像是上面提到的架构问题的补丁)

3 个答案:

答案 0 :(得分:4)

您需要致电

samplesDbEntities.SaveChanges();

在重新查询对象之前。

var samplesDbEntities = new SamplesDBEntities(); 
var blogId = Guid.NewGuid(); 
samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); 

samplesDbEntities.SaveChanges();

var objectSetResult = samplesDbEntities.Blogs 
                                   .Where(p => p.BlogID == blogId) 
                                   .SingleOrDefault(); 

<强>更新

您没有在objectSetResult中获取添加的用户的原因是调用IQueryable对象的SingleOrDefault方法会导致数据库查询(根据“where”条件生成实际的SQL查询字符串等) ,并且由于该对象(尚未)在数据库中,因此不会返回。 但是,新对象附加到上下文,并且它的EntityState设置为“已添加”。根据MSDN,处于已添加状态的对象在ObjectStateEntry中没有原始值。对象上下文中的对象状态由ObjectStateManager管理。因此,如果要检查对象是否已真正附加,可以通过调用GetObjectStateEntry来获取它:

var samplesDbEntities = new SamplesDBEntities();
Blog blog = new Blog() { BlogID = Guid.NewGuid() };
samplesDbEntities.Blogs.AddObject("Blogs", blog);

Blog addedBlog = (Blog)context.ObjectStateManager.GetObjectStateEntry(blog).Entity;

另请注意,检索到的对象的EntityState是“已添加”。

总结一下 - 关于你是否正确实施UnitOfWork的初步问题,我不明白为什么不这样做。它确实维护了一个对象列表并跟踪了更改等等。但是,您遇到的问题与您从底层提供程序获取数据的事实有关,而不是从当前连接到该对象的对象列表中获取数据。上下文。

答案 1 :(得分:1)

您示例中违反的模式不是工作单元模式,而是身份映射。

工作单元跟踪您的代码对对象所做的更改,而不是您手动处理。

Identity Mapping模式将对象上下文设置为具有单个主键值的单个实体实例。

对我来说很奇怪,但实体框架(以及LINQ 2 SQL)并没有在每种情况下映射对象标识,上面描述的情况就是这种情况之一。

答案 2 :(得分:0)

感谢您澄清您的观点。我将此作为另一个答案添加,因为在这个问题上有很多话要说。

AFAIK,对UoW没有严格的通用定义,所以当然这个话题还有争议。我的观点如下:

  1. 您正在向上下文添加实体,但尝试从数据库中获取它。断定ObjectContext不是UoW的正确实现是不合逻辑的。

  2. 如果要将实体添加到上下文中,以便稍后在将更改保留到db之前将其删除,则不使用EF,因为它是要使用的。通常,您不应该使用ObjectStateManager来执行此操作,但您可以:

    Blog addedBlog = context.
             ObjectStateManager.
             GetObjectStateEntries(EntityState.Added).
             Where(ent => (ent.Entity is Blog) && ((Blog)ent.Entity).BlogID == blogID).
             Select(ent => ent.Entity as Blog).
             SingleOrDefault();
    
  3. 工作单元是一个上下文对象,用于维护业务实体列表,跟踪一个业务事务期间其状态的更改。 EF ObjectContext会这样做吗?是。它是否提供合理的语法来检索状态为“已添加”的对象?不,但这并不是“正确”UoW实施的要求。不要忘记 - EF是一个ORM,目标是跟踪代码中数据库的更改,而不是代码的不同部分之间的更改(这就是您的业务逻辑)。

  4. 关于:“如果我必须自己坚持每个实体而不是批处理”,那么UoW的重点是什么? - 关键是你可以在上下文中添加一堆对象,然后将它们全部保存在一个人打电话给SaveChanges。正如我已经提到的,上下文并不意味着用于“携带”您的业务对象。但是,如果您愿意,可以从ObjectStateManager中检索它们,而不必持久更改数据库。