RIA Services Repository Save does not work? - entity-framework

Doing my first SL4 MVVM RIA based application and i ran into the following situation:
updating a record (EF4,NO-POCOS!!) in the SL-client seems to take place, but values in the dbms are unchanged. Debugging with Fiddler the message on save is (amongst others):
EntityActions.nil� b9http://schemas.microsoft.com/2003/10/Serialization/Arrays^HasMemberChanges�^Id�^ Operation�Update
I assume that this says only: hey! the dbms should do an update on this record, AND nothing more! Is that right?!
I 'm using a generic repository like this:
public class Repository<T> : IRepository<T> where T : class
{
IObjectSet<T> _objectSet;
IObjectContext _objectContext;
public Repository(IObjectContext objectContext)
{
this._objectContext = objectContext;
_objectSet = objectContext.CreateObjectSet<T>();
}
public IQueryable<T> AsQueryable()
{
return _objectSet;
}
public IEnumerable<T> GetAll()
{
return _objectSet.ToList();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> where)
{
return _objectSet.Where(where);
}
public T Single(Expression<Func<T, bool>> where)
{
return _objectSet.Single(where);
}
public T First(Expression<Func<T, bool>> where)
{
return _objectSet.First(where);
}
public void Delete(T entity)
{
_objectSet.DeleteObject(entity);
}
public void Add(T entity)
{
_objectSet.AddObject(entity);
}
public void Attach(T entity)
{
_objectSet.Attach(entity);
}
public void Save()
{
_objectContext.SaveChanges();
}
}
The DomainService Update Method is the following:
[Update]
public void UpdateCulture(Culture currentCulture)
{
if (currentCulture.EntityState == System.Data.EntityState.Detached)
{
this.cultureRepository.Attach(currentCulture);
}
this.cultureRepository.Save();
}
I know that the currentCulture-Entity is detached. What confuses me (amongst other things) is this: is the _objectContext still alive? (which means it "will be"??? aware of the changes made to record, so simply calling Attach() and then Save() should be enough!?!?)
What am i missing?
Development Environment: VS2010RC - Entity Framework 4 (no POCOs)
Thanks in advance

You are attaching the culture in the context, but you are not telling the context that the object has actually changed.
The generated code I have on my machine is:
public void UpdateDepartment(Department currentDepartment) {
if ((currentDepartment.EntityState == EntityState.Detached)) {
this.ObjectContext.AttachAsModified(currentDepartment, this.ChangeSet.GetOriginal(currentDepartment));
}
}
What matters is the 'AttachAsModified'.

Timores pointed me in the correct direction, the solution (as far as my problem concerns) is very simple: simply add this method to the repository and we're done:
public void AttachModified(T entity)
{
_objectSet.Attach(entity);
_context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
}
Now instead of calling Attach() we call AttachModified().
Thank you Timores!

Related

Generic Repository EntityFramework 6 Implementation

I have been assigned a new project and I have decided to give EF a go.In this project all I do is getting data there is no persistence.I have to implement some caching and that's it.
Reading about Repository patterns I have found tons of code samples etc... they seem all wrong to me.They implement a one to one Entity to Repository.
In my project I just need reading data not saving etc... just reading.I have 100s entities I cannot create 100s repository seems all wrong.
I have decided to start simple and I all need is this:
public interface IRepository : IDisposable
{
IEnumerable<T> GetAll<T>() where T : class;
IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class;
T GetOne<T>(Expression<Func<T, bool>> predicate) where T : class;
}
public class Repository : IRepository
{
public IEnumerable<T> GetAll<T>() where T : class
{
return ???.ToArray();
}
public IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class
{
return ???.Where(predicate).ToArray();
}
public T GetOne<T>(Expression<Func<T, bool>> predicate) where T : class
{
return ???.Where(predicate).FirstOrDefault();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
What I am struggling with is where i put the "???" that should be my IdbSet.
How could I Implement my concrete repository?Any suggestions or noddy test sample will do.
many thanks
First, you better change the GetAll() and Find() methods to return IQueryable<T> instead of IEnumerable<T>, so that further querying on the dataset would be implemented using Linq-to-Entities.
As of the EF implementation, try something like this:
public class EFRepository : DbContext, IRepository
{
// ctor:
// pass a full connecting-string, or "name=someName" from configuration
public EFRepository(string connectionStringOrName) : base(connectionStringOrName)
{
// init sets
this.Entities1 = this.Set<EntityOfSomeType>();
this.Entities2 = this.Set<EntityOfOtherType>();
}
public IEnumerable<T> GetAll<T>() where T : class
{
return this.Set<T>().ToArray();
}
public IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class
{
return this.Set<T>().Where(predicate).ToArray();
}
public T GetOne<T>(Expression<Func<T, bool>> predicate) where T : class
{
return this.Set<T>.FirstOrDefault(predicate);
}
public void Dispose()
{
base.Dispose();
}
// Your DbSets...
public IDbSet<EntityOfSomeType> Entities1 { get; set; }
public IDbSet<EntityOfAnotherType> Entities2 { get; set; }
}
(I used DbContext with the assumption that you're going code-first)

What's DataService Best practice using Entity Framework and Repository and UnitOfWork Patterns

I'm using EF and MVVM pattern. My question is about the Data Access Layer. in DAL I have the following classes:
MyObjectContext which is technically the standard ObjectContext now, but some Unit-of-work methods will be added to it later.
Repository<TModel> which handles the most needed queries (such as Add, GetAll, ...) on different ObjectSets.
A bunch of DataServices which make use of repositories to provide a higher level of data access for Core.
The project I'm working on is a business application with about 100 EntitySets so far, and there are times when a single interaction of a user can involve up to 20 different EntitySets (updating most of them). I currently add .Include(params string[]) to my queries to prevent ObjectContextDisposedException but it doesn't seem to be a reliable solution.
The question is should I create an instance of MyObjectContext (and therefore Repository) in each of DataService methods (like the following codes, it seems to me that the ability of Unit of work would be useless in this case) or should I create it outside of DataService and pass it to the DataServices through their constructors (or directly to each of the DataService methods) to handle a bunch of database actions (different tables and queries) together. And how?
Here's what MyObjectContext looks like:
public class MyObjectContext : ObjectContext, IUnitOfWork
{
public MyObjectContext()
: base("name=EdmContainer", "EdmContainer")
{
ContextOptions.LazyLoadingEnabled = true;
}
#region IUnitOfWork Members
public void Commit()
{
SaveChanges();
}
#endregion
}
This is how Repository looks like:
public class Repository<TModel>
{
private readonly SoheilEdmContext _context;
public Repository(IUnitOfWork unitOfWork)
{
if (unitOfWork == null)
throw new ArgumentNullException("unitOfWork");
_context = unitOfWork as SoheilEdmContext;
}
public TModel FirstOrDefault(Expression<Func<TModel, bool>> where)
{
return _context.CreateObjectSet<TModel>().FirstOrDefault(where);
}
public void Add(TModel entity)
{
_context.CreateObjectSet<TModel>().AddObject(entity);
}
...
}
And this is how a common DataService looks like:
public class JobDataService : IDataService<Job>
{
#region IDataService<Job> Members
public Job GetSingle(int id)
{
Job model = null;
using (var context = new MyObjectContext())
{
var repos = new Repository<Job>(context);
model = repos.FirstOrDefault(x => x.Id == id);
}
return model;
}
public IEnumerable<Job> GetAll()
{
using (var context = new MyObjectContext())
{
var repos = new Repository<Job>(context);
var models = repos.GetAll();
return models;
}
}
public IEnumerable<Job> GetActives()
{
throw new NotImplementedException();
}
public int AddModel(Job model)
{
using (var context = new MyObjectContext())
{
var repos = new Repository<Job>(context);
repos.Add(model);
context.SaveChanges();
}
}
public void UpdateModel(Job model)
{
throw new NotImplementedException();
}
public void DeleteModel(Job model)
{
using (var context = new MyObjectContext())
{
var repos = new Repository<Job>(context);
var model = repos.FirstOrDefault(x => x.Id == model.Id);
if (model == null) return;
repos.Delete(model);
context.SaveChanges();
}
}
#endregion
}
Any kind of idea or insight would be appreciated.
You can create an instance of MyObjectContext in each service, like JobDataService, however, it makes your code messy and it is hard to maintain. Create instance of MyObjectContext outside of DataService is better. What you have now, if you have 100 EntitySets, you have to create 100 DataServices. That is because the use of "Repository Pattern" and "UnitOfWork" here is not efficient. I would suggest doing the following:
ObjectContext
public class MyObjectContext : ObjectContext
{
public MyObjectContext() : base("name=EdmContainer", "EdmContainer")
{
ContextOptions.LazyLoadingEnabled = true;
}
#region IUnitOfWork Members
public void Commit()
{
SaveChanges();
}
#endregion
}
Generic Repository
public interface IRepository<TModel> where TModel : class
{
void Add(TModel entity);
IEnumerable<TModel> GetAll();
// Do some more implement
}
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
private readonly ObjectContext _context;
public Repository(ObjectContext context)
{
_context = context;
}
public virtual void Add(TModel entity)
{
_context.CreateObjectSet<TModel>().AddObject(entity);
}
public virtual IEnumerable<TModel> GetAll()
{
return _context.CreateObjectSet<TModel>();
}
}
UnitOfWork
public interface IUnitOfWork : IDisposable
{
IRepository<Job> Jobs { get; }
IRepository<User> Users { get;}
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly SoheilEdmContext _context;
private readonly IRepository<Job> _jobRepository;
private readonly IRepository<User> _userRepository;
public UnitOfWork(SoheilEdmContext context)
{
_context = context;
_jobRepository = new Repository<Job>(_context);
_userRepository = new Repository<User>(_context);
}
public IRepository<Job> Jobs{get { return _jobRepository; }}
public IRepository<User> Users{get { return _userRepository; }}
public void Commit(){_context.Commit();}
public void Dispose()
{
if (_context != null)
{
_context.Dispose();
}
GC.SuppressFinalize(this);
}
JodDataSerivce
public interface IDataService
{
IEnumerable<Job> GetAll();
}
public class DataService : IDataService
{
private readonly IUnitOfWork _unitOfWork;
public DataService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IEnumerable<Job> GetAll()
{
return _unitOfWork.Jobs.GetAll();
}
}
Here I used interface for implementing everything, if you want to do the same, you need to use IoC Container. I used the "Simple Injector", you can find it here:
Simple Injector
One more suggestion, if you feel like you have too many I/O operations to implement, like database access, querying data, etc., you should consider using Asynchronous. Below is a good video on Asynchronous.
How to Build ASP.NET Web Applications Using Async

Should I define a repository for each entity

I have been learning about MVC and I am using Entity Framework. What I am trying to understand is repositories. Every tutorial I've read deals with one entity and at that level I have a understanding, but what about multiple tables. I use a variation of code-first, where I associate my model classes with an existing database. In my database,there are three tables; User, Journey and UserJourney (linked table). User and Journey have a many-to-many relationship. Should I have a repository for each entity? Has aggregates any use here? In the long run I want to query the database to find user's journeys and pass to a view.
My question is perhaps vague, but I am quite confused on this matter, so any help in understanding this would be appreciated!
Normally repositories should not be defined for each entity but rather per aggregate root. You have entities that cannot live by themselves, but are related to some parent entity. This parent entity is called aggregate root and you should have a repository for each of them.
Search for a concept called GenericRepository. It will help in getting rid of the repository for each entity problem. Sample below:
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> GetAll();
T SingleOrDefault(Expression<Func<T, bool>> predicate);
IEnumerable<T> Get(Expression<Func<T, bool>> predicate);
void Insert(T entity);
void Update(T entity);
void Delete(object id);
void Delete(T entity);
}
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
readonly MyDbContext _context;
readonly DbSet<T> _dbSet;
public GenericRepository(PfsDbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.AsEnumerable();
}
public T SingleOrDefault(Expression<Func<T, bool>> predicate)
{
return _dbSet.Where(predicate).SingleOrDefault();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
return _dbSet.Where(predicate);
}
public void Insert(T entity)
{
_dbSet.Add(entity);
}
public void Update(T entityToUpdate)
{
_dbSet.Attach(entityToUpdate);
_context.Entry(entityToUpdate).State = EntityState.Modified;
}
public void Delete(T entity)
{
if (_context.Entry(entity).State == EntityState.Detached)
{
_dbSet.Attach(entity);
}
_dbSet.Remove(entity);
}
public void Delete(object id)
{
var entityToDelete = _dbSet.Find(id);
Delete(entityToDelete);
}
}
You can then use it as
var userRepository = new GenericRepository<User>(_context);
var journeyRepository = new GenericRepository<Journey>(_context);

UnitOfWork and Entity Framework Contexts

So the problem I am trying to solve is this; We are using Entity Framework to access our Oracle database that has 1200-1500 tables. Now mind you we are not accessing them all, but possibly could have 800+ to access. We are using the UnitOfWork --> Repository --> Service pattern and that works great, but we are trying to figure out if we should have one big DbContext, or multiple little contexts that are specific to the task at hand.
Our UnitOfWork is setup using an EFUnitOfWorkBase like so:
public abstract class EFUnitOfWorkBase : IUnitOfWork
{
private bool isDisposed = false;
public DbContextBase Context { get; set; }
protected EFUnitOfWorkBase(DbContextBase context)
{
Context = context;
}
public int Commit()
{
return Context.SaveChanges();
}
public void Dispose()
{
if (!isDisposed)
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
isDisposed = true;
if (disposing)
{
if (this.Context != null)
this.Context.Dispose();
}
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : Common.EntityBase<TEntity>
{
return new Repository<TEntity>(this);
}
}
Any unit of work we create extends that base one and provides the context like so:
public class EmployeeDirectoryUnitOfWork : EFUnitOfWorkBase
{
public EmployeeDirectoryUnitOfWork(string connectionString)
: base(new EmployeeDirectoryContext(connectionString))
{
}
}
The DbContext is passed a connection string through the unit of work.
The Repository looks like this:
public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContextBase Context;
protected DbSet<TEntity> EntitySet;
public RepositoryBase(EFUnitOfWorkBase unitOfWork)
{
Enforce.ArgumentNotNull(unitOfWork, "unitOfWork");
Context = unitOfWork.Context;
EntitySet = Context.Set<TEntity>();
}
public TEntity Add(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Add(entity);
}
public TEntity Attach(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Attach(entity);
}
public TEntity Delete(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Remove(entity);
}
public System.Linq.IQueryable<TEntity> Query()
{
return EntitySet.AsQueryable();
}
public TEntity Save(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
Attach(entity);
Context.MarkModified(entity);
return entity;
}
}
Any suggestions on how to best handle this situation?
In such a case when you have a large application like this, I think you should probably go for a more Domain Driven Design approach and split the contexts into some separate, bounded contexts. This way when later developers are adding features to the program they will be confined to only being able to access certain tables depending on which context they will be using there.
For better information, Julie Lerman recently came out with a course on Pluralsight about Entity Framework in the Enterprise that's really good. She posted a small clip of it (actually about bounded contexts) on this site. It's a very good course, and I highly recommend it, especially for what you appear to be doing.

Multiple telerik MVC grids in TabStrip not working with ninject and entity framework, unit of work, repository pattern

I am creating an ASP.NET MVC 3 e-commerce website and I am currently working on the admin area where you can add/edit products. To create the UI for the product page I am using Telerik MVC controls.
My problem is that when I added a second telerik grid which both retrieve data from the database through an ajax call I receive a couple different errors listed below:
{"There is already an open DataReader associated with this Command
which must be closed first."}
{"The connection was not closed. The connection's current state is
connecting."}
Database Context Code
public interface IUnitOfWork
{
void Commit();
}
public class GSPDataContext : DbContext, IUnitOfWork
{
/* (omitted) IDbSet's for entities */
public GSPDataContext()
: base("GSPConnectionString")
{
}
public virtual IDbSet<T> DbSet<T>() where T : class
{
return Set<T>();
}
public virtual void Commit()
{
base.SaveChanges();
}
}
Generic Repository Code
public class Repository<T> : IRepository<T> where T : class
{
private GSPDataContext m_dataContext;
private readonly IDbSet<T> m_entity;
public Repository(GSPDataContext dataContext)
{
if (dataContext == null)
throw new ArgumentException();
m_dataContext = dataContext;
m_entity = m_dataContext.Set<T>();
}
public T GetById(int id)
{
return this.m_entity.Find(id);
}
public void Insert(T entity)
{
if (entity == null)
throw new ArgumentException();
this.m_entity.Add(entity);
//this.m_dataContext.SaveChanges();
}
public void Delete(T entity)
{
if (entity == null)
throw new ArgumentException();
this.m_entity.Remove(entity);
//this.m_dataContext.SaveChanges();
}
public virtual IQueryable<T> Table
{
get
{
return this.m_entity;
}
}
}
Ninject Code
private static void RegisterServices(IKernel kernel)
{
//Customer
kernel.Bind<IAddressValidationService>().To<AddressValidationService>().InRequestScope();
kernel.Bind<ICustomerService>().To<CustomerService>().InRequestScope();
kernel.Bind<ICustomerProductService>().To<CustomerProductService>().InRequestScope();
//Authentication
kernel.Bind<IOpenIDLoginService>().To<OpenIDLoginService>().InRequestScope();
kernel.Bind<IAuthenticationService>().To<FormsAuthenticationService>().InRequestScope();
//Products
kernel.Bind<IProductService>().To<ProductService>().InRequestScope();
kernel.Bind<IRecentlyViewedProductService>().To<RecentlyViewedProductService>().InRequestScope();
kernel.Bind<IProductPictureService>().To<ProductPictureService>().InRequestScope();
kernel.Bind<ICategoryService>().To<CategoryService>().InRequestScope();
kernel.Bind<IPictureService>().To<PictureService>().InRequestScope();
//Shopping Cart
kernel.Bind<IShoppingCartService>().To<ShoppingCartService>().InRequestScope();
//Shipping and Payment
kernel.Bind<IShippingService>().To<ShippingService>().InRequestScope();
kernel.Bind<IPaymentService>().To<PaymentService>().InRequestScope();
//Orders
kernel.Bind<IOrderCalculationService>().To<OrderCalculationService>().InRequestScope();
kernel.Bind<IOrderProcessingService>().To<OrderProcessingService>().InRequestScope();
kernel.Bind<IOrderService>().To<OrderService>().InRequestScope();
//
kernel.Bind<IEncryptionService>().To<EncryptionService>().InRequestScope();
kernel.Bind<ILogger>().To<LoggingService>().InRequestScope();
kernel.Bind<IWebManager>().To<WebManager>().InRequestScope();
//Messages
kernel.Bind<IEmailService>().To<EmailService>().InRequestScope();
kernel.Bind<IMessageTemplateService>().To<MessageTemplateService>().InRequestScope();
kernel.Bind<IWorkflowMessageService>().To<WorkflowMessageService>().InRequestScope();
//Data
kernel.Bind<GSPDataContext>().ToSelf().InSingletonScope();
kernel.Bind<IUnitOfWork>().ToMethod(ctx => ctx.Kernel.Get<GSPDataContext>()).InSingletonScope();
kernel.Bind(typeof (IRepository<>)).To(typeof (Repository<>)).InRequestScope();
kernel.Bind<IWorkContext>().To<WebWorkContext>().InRequestScope();
}
I suspect it has something to do with how ninject is managing the lifetimes of the various services, but I am not sure what I need to do to make it work.
Any advice would be much appreciated.
Thanks
UPDATE
According to Remo's comment I change my code to the following:
//Data
kernel.Bind<GSPDataContext>().ToSelf().InRequestScope();
kernel.Bind<IUnitOfWork>().ToMethod(ctx => ctx.Kernel.Get<GSPDataContext>()).InRequestScope();
kernel.Bind(typeof (IRepository<>)).To(typeof (Repository<>)).InRequestScope();
And I am now getting the following error:
The ObjectContext instance has been disposed and can no longer be used
for operations that require a connection.
Any ideas?
No, it has nothing to do with how Ninject manages lifetimes. But it has to do how you configured the lifecycles.
It is important that a new DbContext is used for each request. This has to be InRequestScope.