2014-01-26 55 views
12

DbSet<TEntity>.Add方法返回一个实体。我通常会预期Add操作有一个void返回类型。为什么DbSet Add会返回一个实体实例而不是void?

当我看EntityFramework source code,我看到了下面的实现:

public virtual TEntity Add(TEntity entity) 
    { 
     Check.NotNull(entity, "entity"); 

     GetInternalSetWithCheck("Add").Add(entity); 
     return entity; 
    } 

GetInternalSetWithCheck返回一个InternalSet<TEntity>

InternalSet<TEntity>Add方法,有趣的是在其签名返回void类型:

public virtual void Add(object entity) 

我担心的是我是否需要在修改与实体相关的实体以及添加到DbSet时要小心。

E.g.有没有情况

var entity = new MyEntity(); 
_dbSet.Add(entity); 
entity.SomeDatModifyingMethod(); 
_dbContext.SaveChanges(); 

可能给不同的行为比

var entity = new MyEntity(); 
entity.SomeDatModifyingMethod(); 
_dbSet.Add(entity); 
_dbContext.SaveChanges(); 

或不同的行为:

var entity = new MyEntity(); 
entity = _dbSet.Add(entity); 
entity.SomeDatModifyingMethod(); 
_dbContext.SaveChanges(); 

在基本的默认实现,它不会永远的事,因为它只是总是返回完全相同的实例。然而,Add方法是virtual,所以它可以被覆盖(虽然在公共源代码中,唯一的覆盖是测试加倍 - 但我不确定源代码实际上是否包含例如SqlServer支持实现)。

为什么DbSet Add返回实体实例而不是void?

回答

4

TEntity是引用类型,所以什么被添加到InternalSet<T>将是一个参考的实体,而不是价值。在将实体内容添加到集合之前或之后更改其内容无关紧要,因为它从未在数据库中创建。无论如何,将会执行INSERT或等效。

至于为什么Add回报TEntity,它希望它的,因为它允许类似的事情:

_dbSet.Add(new MyEntity()).SomeDatModifyingMethod(); 
_dbContext.SaveChanges(); 
+0

这主要是有道理的 - 只要'Add'方法永远不会像返回一个代理那样 - 可能用于更改跟踪? - 在这种情况下,添加后重新分配参考可能很重要? (例如,最后一个代码示例) – Nathan

+0

虽然想到了它,但我不知道为什么你需要更改跟踪一个新增的实体... – Nathan

+0

'Add'可能不是'SaveChanges '。如果有'删除'呢? –

6

它可以让你写一个“查找或添加”模式

var person = context.People.Find(ssn) ?? context.People.Add(new Person 
{ 
    SocialSecurityNumber = ssn, 
    FirstName = "John", 
    LastName = "Doe" 
}); 
相关问题