2010-06-25 46 views
6

实体框架4 - STE - 简单DB与具有BlogID PK柱单个表博客...实体框架ObjectContext是否正确实现了工作单元模式?

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在这里有null值?

(是的,我知道ObjectStateManager的,但对我来说是多为上提到的建筑问题的补丁的)

回答

1

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

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

标识映射模式实现对象上下文以使主键的单个值具有单个实体实例。

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

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方法(实际SQL查询字符串产生的原因根据“where”条件等),并且由于该对象不在数据库中,因此不会返回。 但是,新对象附加到上下文,并且它的EntityState被设置为“已添加”。根据MSDN,处于Added状态的对象在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的正确实现,我不明白为什么不这样做。它确实保留了对象列表并跟踪更改等等。但是,您遇到的问题与您从基础提供程序获取数据而不是从当前附加到上下文。

+0

-1因为这是不是在确切的问题上回答“实体框架ObjectContext是否正确实施工作单元模式?” – Restuta 2010-06-25 15:25:56

+0

够公平的。查看更新的答案。 – Yakimych 2010-06-25 17:04:24

+2

我的用例是实体在持久性发生之前被添加和检索 - 如果我必须自己坚持每个实体而不是批量持久化,那么UoW又有什么意义呢? 至于更新代码,你不觉得我必须知道我需要使用ObjectStateManager的事实不好(泄漏基础设施)吗? 不是我微不足道的样品,但“得到”可以在完全不同的地方发生在哪里我不知道,如果补上一的情况下。为什么这不会被封装在OBjectSet本身内部(比如UoW应该这样做)并且只是在持久化过程中被识别? – 2010-06-25 17:58:31

0

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

AFAIK,UoW没有严格的普遍定义,所以当然这个话题是争论的话题。我的观点如下:

  1. 您正在添加一个实体到上下文,但试图从数据库中获取它。结论是ObjectContext不是UoW的正确实现是不合逻辑的。

  2. 如果您将实体添加到上下文中,以便稍后在出于某种原因将其更改为出于某种原因而退出之前,您未使用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,目标是跟踪代码中数据库的变化,而不是代码的不同部分之间的变化(这就是您的业务逻辑)。

和关于“什么是UOW的点,如果我要坚持自身的每一个实体,而不是批量” - 问题是,你可以一堆对象添加到上下文,然后通过调用SaveChanges一步一步地坚持它们。正如我已经提到的那样,上下文并不意味着用于“携带”您的业务对象。但是,如果您愿意,您可以从ObjectStateManager中检索它们,而不必对数据库进行更改。

+0

你说:“问题是,你可以一堆对象添加到上下文,然后通过调用的SaveChanges坚持他们都在一个去” 我有100%的同意(这就是我说的)。所描述的方式EF4的作品,我可以从我的代码的不同部分添加具有相同ID的2个帖子 - 一切都很好,直到持久 - 当PK违反会发生。 我不需要EF4 *如何工作的更多解释* - 我知道这一点,我认为(架构)是有缺陷的。 好像SO问题是不是有这样的讨论,所以我会写一个博客帖子有提供更多详细信息,这... – 2010-06-27 10:52:34

+0

我投的问题被关闭的“太主观了”,但我需要4个声音的良好培养基为了被关闭:) – 2010-06-27 10:54:01