I am using an example off this link to update database tables in SQL Server 2008 following the repository and Unit of Work pattern.
While I have got the Insert working. I am having a hard time getting the update and delete working. The update gives no error, and does not update. The delete gives an InvalidOperationException like this The object cannot be deleted because it was not found in the ObjectStateManager.
For insert and delete I am using the IObjectSet methods as given in the example. For Update I am using the IObjectSet.Attach(entity) method to which I send the modified object.
Code for Repository and Unit of work classes below:
Repository Class
namespace DataAccess {
public interface IGenericRepository<T> where T : class { void AddRow(T entity); void UpdateRow(T entity); void Delete(T entity); } public abstract class GenericRepository<T> : IGenericRepository<T> where T : class { protected IObjectSet<T> _objectSet; public GenericRepository(ObjectContext Context) { _objectSet = Context.CreateObjectSet<T>(); } public void AddRow(T entity) { _objectSet.AddObject(entity); } public void UpdateRow(T entity) { _objectSet.Attach(entity); } public void Delete(T entity) { _objectSet.DeleteObject(entity); } } }
Unit Of Work Class
namespace DataAccess
{
public interface IUnitOfWork
{
IGenericRepository<User> Users { get; }
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly ObjectContext _context;
private UserRepository _userRepository;
public UnitOfWork(ObjectContext Context)
{
if (Context == null)
{
throw new ArgumentNullException("Context wasn't supplied");
}
_context = Context;
}
public void Commit()
{
_context.SaveChanges();
}
public IGenericRepository<User> Users
{
get
{
if (_userRepository == null)
{
_userRepository = new UserRepository(_context);
}
return _userRepository;
}
}
}
}
Finally this is how I use it for update in my calling code
public void UpdateUser(UserData userData)
{
using (mEntities context = new mEntities())
{
UnitOfWork uow = new UnitOfWork(context);
User usr = new User(); //This is the Entity Framework class
usr.ID = userData.RowID;
usr.UserName = userData.Username; //usr.UserName is the primar开发者_开发百科y key in the table
uow.Users.UpdateRow(usr);
uow.Commit();
}
}
But the update doesn't happen. What am I doing wrong here? I am using VS2010 with EF 4
Thanks for your time...
After you attached an item in UpdateRow
you need to mark it as modified. Entities are attached in the state Unchanged. However to modify the state you'll need access to the ObjectStateManager
which is a property of the context. In EF 4.1 I was told there's a method Entry()
in the context that allows you to set the state as well.
To delete an entity it has to be present in the context. If it hasn't been loaded you'll have to attach it before deleting it.
Also be aware about the difference between using new()
and CreateObject<T>()
.
So the way that worked was to change the update method in the Generic repository class
public void UpdateRow(T entity)
{
_objectSet.Attach(entity);
_context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
_context.SaveChanges();
}
The UnitOfWork class doesn't need the Commit() method anymore. so now my calling code does just this..
public void UpdateUser(UserData userData)
{
using (mEntities context = new mEntities())
{
UnitOfWork uow = new UnitOfWork(context);
User usr = new User(); //This is the Entity Framework class
usr.ID = userData.RowID;
usr.UserName = userData.Username; //usr.UserName is the primary key in the table
uow.Users.UpdateRow(usr);
//uow.Commit();
}
}
Hope this helps anyone else. Although I havnt tested this thoroughly I think this should work for most situations.
精彩评论