2

I'm trying to apply the unit of work pattern as described in this blog, but have bumped into the following problem: If I inject the associated DbSet into the repo only, e.g.

public ArticleRepository(DbSet<Article> articles)
{
   this.articles = articles;
}

then how do I update records or set their status to modified?

Before I used

public void Update(Article article)
{
   this.context.Entry(article).State = EntityState.Modified;
}

but with the new approach I don't have access to DbContext anymore. Neither DbSet.Add nor DbSet.Attach will work here, so how can I update the object in the context?

Thorsten Westheider
  • 10,572
  • 14
  • 55
  • 97
  • 1
    `IGenericRepository` should be totally by your design. You can add some method to set state for an entity there. That kind of interface really looks like a wrapper. So if possible try exposing the core part (DbContext, ...) via some other hidden interface. When needed you can always access to the core to perform some ***advanced*** task. As a wrapper, sometimes it cannot provide full operations as what you can do with core parts. To me that pattern is based much on the so-called ***wrapper***. – Hopeless Sep 26 '15 at 09:41
  • 1. You can access the context from the `DbSet`. 2. Don't inject the `DbSet`, inject the context itself and then set `this.articles` using the context. 3. Do you know why are you abstracting away the context at all? Entity Framework context is already having a built-in Unit Of Work mechanism. – haim770 Dec 10 '15 at 08:09

1 Answers1

3

System.Data.Entity.Migrations.IDbSetExtensions contains the IDbSet extension AddOrUpdate<TEntity>. This will update the entity.

Some people like the advantage of not knowing whether they are adding a new entity or changing an existing one.

However, if you really want an error if you are updating an item that is not added yet, take a look at the Source Code of IDbSetExtensions.AddOrUpdate

Here you can see that the function first checks if the item exists and depending on the result adds or updates it as follows:

var existing = set.SingleOrDefault
    (Expression.Lambda<Func <TEntity, bool>> (matchExpression, new[]
        {parameter}));

if (existing != null)
{   // entity exists: update it
    foreach (var keyProperty in keyProperties)
    {
        keyProperty.Single().SetValue
            (entity, keyProperty.Single().GetValue (existing, null), null);
    }
    internalSet.InternalContext.Owner.Entry(existing)
        .CurrentValues.SetValues (entity);
}
else
{   // not existing entity: Add it
    internalSet.Add(entity);
}

If you don't want the AddOrUpdate, but really only an update, consider Creating your own Extension method for IDbSet. See Extension Methods (C# Programming Guide)

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116