MVC3 EF Ninject Generic Repository - asp.net-mvc-3

I'm working on a generic repository using Entity Framework/MVC3/Ninject.MVC3. The interface looks like this.
public interface IRepository<TEntity> where TEntity : class
{
IQueryable<TEntity> Query { get; }
void Add(TEntity entity);
void Edit(TEntity entity);
void Delete(TEntity entity);
}
My Concrete implementation looks like this.
public class EFRepository<T> : IRepository<T> where T : class
{
private EFDbContext context = new EFDbContext();
public IQueryable<T> Query
{
get { return context.Set<T>().AsQueryable(); }
}
public void Add(T entity)
{
context.Set<T>().Add(entity);
context.SaveChanges();
}
public void Edit(T entity)
{
context.Entry<T>(entity).State = System.Data.EntityState.Modified;
context.SaveChanges();
}
public void Delete(T entity)
{
context.Set<T>().Remove(entity);
context.SaveChanges();
}
}
Ninject has the binding
kernel.Bind(typeof(IRepository<>)).To(typeof(EFRepository<>));
What I need to do is get the last insert ID in the concrete implementation. I have a transaction table that will get an insert based on the last table and insert ID. I could call the transaction from the controller, but I'd rather just get it all done in the Data Access Layer, so I can easily write the transaction after the last insert/update.
First, is the above example the proper way to implement the generic repository. Second is there a way to get the data I want through this method?

When you call Add on an entity, and the table has an identity column (auto increment) then you can just check the entity after the SaveChanges() and it will contain the generated ID.

Related

Repository Parameter in controller asp.net mvc

I try to learn repository.I created a class below,
public class Repository<T> where T : class
{
ObjectContext _context;
IObjectSet<T> _objectSet;
DBEntities db = new DBEntities ();
public void Delete(T entity)
{
_objectSet.DeleteObject(entity);
_context.SaveChanges();
}
}
}
I try to use void Delete in my controller below,
public ActionResult Index()
{
var something = new Repository<Department>();
something.Delete(.......); // What i must add to delete method ? How can i delete data from database ?
return View();
}
If i write int value to "something.Delete(2); it does not work, i do not know what to add here,how can i use repository ?
Try this article here:
The Repository Pattern Example in C#
MSDN ObjectContext.DeleteObject Method

ObjectContext not retrieving recent changes

This code works fine, However, if I run execute a storedprocedure in my unit of work class (or any update, delete, add operation), I'm still getting original the data. Actually, I have already a solution(posted below in controller) but Im sure this is not the most elegant way, I hope someone can help me refactor the code. please help. Thanks
My unit of work
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly ObjectContext _context;
private BookRepository _books;
public UnitOfWork(ObjectContext context)
{
if (context == null)
{
throw new ArgumentNullException("Context was not supplied");
}
_context = context;
}
public IRepository<Book> Books
{
get
{
if (_books== null)
{
_books= new BookRepository (_context);
}
return _books;
}
}
public void UpdateAuthor(int id)
{
_context.ExecuteStoreCommand("sp_UpdateAuthor #param1",
new SqlParameter("param1", id));
}
public void Commit()
{
_context.SaveChanges();
}
Book Repository
public class BookRepository : Repository<Book>
{
public BookRepository (ObjectContext context)
: base(context)
{
}
public override Machine GetById(object id)
{
return _objectSet.SingleOrDefault(s => s.Id== (int)id);
}
}
Generic Repository
public abstract class Repository<T> : IRepository<T>
where T : class, IAuditEntity
{
protected IObjectSet<T> _objectSet;
public Repository(ObjectContext context)
{
_objectSet = context.CreateObjectSet<T>();
}
public abstract T GetById(object id);
public IEnumerable<T> GetAll()
{
return _objectSet;
}
public IEnumerable<T> Query(Expression<Func<T, bool>> filter)
{
return _objectSet.Where(filter);
}
public void Add(T entity)
{
_objectSet.AddObject(entity);
}
public void Remove(T entity)
{
_objectSet.DeleteObject(entity);
}
}
Controller Code
public class HomeController : Controller
{
private IUnitOfWork _unitOfWork;
#region Core Action Methods
public HomeController()
{
this._unitOfWork = new UnitOfWork(((IObjectContextAdapter)new BookContext()).ObjectContext);
}
private IEnumerable<BookViewModel> GetBookdsViewModels(int id)
{
//THE CODE WHERE ITS NOT RETURNING THE UPDATED VLAUES
//var query = _unitOfWork.Books.GetAll().Where(d => d.Id== id);
//I WANT TO CHANGE THIS CODE
ObjectContext objectContext = ((IObjectContextAdapter)new BookContext()).ObjectContext;
ObjectSet<Book> set = objectContext.CreateObjectSet<Book>();
set.MergeOption = MergeOption.OverwriteChanges;
var query = from a in set
where a.Id== id && !a.IsDeleted
select a;
return query
.Select(
c => new BookViewModel
{
Id = c.Id ,
Name = c.Name
});
}
I believe the problem is because you're executing things directly against your database, and then trying to refer back to the local copy that's stored in your repository and they're different.
public void UpdateAuthor(int id)
{
_context.ExecuteStoreCommand("sp_UpdateAuthor #param1",
new SqlParameter("param1", id));
}
When you run this query, you're making a change in your db instead of your local - why dont you do something like this:
public void UpdateAuthor(int id)
{
var book = Books.GetById(id);
/* make changes to your book object */
_unit.Save();
}
If you're wanting to make changes using store procs, you're going to have to dispose of your context, and recreate the repo's so that you're working with data from the DB instead of the local copy.
Expanding on Mark Oreta's answer, you need to ensure your Model is updated after manually executing a stored proc on your database. If you must manually call that stored proc then try this afterward:
_context.Entry<Book>(instanceOfAuthor).Reload();
Which might be:
_context.Entry<Book>(_context.Books.GetById(id)).Reload();

EF Using generic and specific repositories

I have the following generic repository:
public class GenericRepository<TEntity> where TEntity : class {
private EFDbContext context;
private DbSet<TEntity> dbSet;
public GenericRepository(EFDbContext context) {}
public IEnumerable<TEntity> GetAll() {}
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "") {}
public TEntity GetByID(int id) {}
public void Insert(TEntity entity) {}
public void Delete(int id) {}
public void Delete(TEntity entity) {}
public void Update(TEntity entity) {}
}
Now I understand how I can use this for my entities, but I don't understand what to do if an entity needs more than just these methods? Say I have an entity called 'Tournament' and I want to get all the groups in that tournament, where would the 'GetTournamentGroups' method go?
Should I, instead of using a generic repository, write a basic repository interface which all the entities' own interfaces inherit from and then just add the additional methods needed for each entity?
You could also simply use
var TournamentGroups = new List<Group>();
using( var GenericRepo = new GenericRepository<Group>())
{
TournamentGroups = GenericRepo.Get(group => group.TournamentId == tournamentId);
}
somewhere with your normal repository. It seems a little overkill to make a class which does this.
Method GetTournamentGroups() seems to belong to the layer above Repository layer:
class TournamentModel
{
private int tournamentId; // initialized in constructor
private GenericRepository<Group> repository; // initialized in constructor
IEnumerable<Group> GetTournamentGroups()
{
return repository.Get( group => group.TournamentId == tournamentId);
}
}
I'd recommend using IQueryable insteam of IEnumerable in your GenericRepository, though. It would be more flexible if you need to apply filters or sort expressions before you make an actual database query.

how to implement generic repository pattern and UoW in NHibernate 3.2

I'm new to NHibernate and I'm trying to impelement Generic Repository Pattern and Unit of Work for using in an ASP.NET MVC 3 application. I googled the title and found new links; but all of them was more complexe to understanding by me. I use StructureMap as my IOC. Can you suggest me some links or blog posts please?
Here are a couple of items to read thru:
Advantage of creating a generic repository vs. specific repository for each object?
How to make a Generic Repository?
The implementation I have used in my most recent project looked like:
public interface IRepository<T>
{
IEnumerable<T> GetAll();
T GetByID(int id);
T GetByID(Guid key);
void Save(T entity);
void Delete(T entity);
}
public class Repository<T> : IRepository<T>
{
protected readonly ISession Session;
public Repository(ISession session)
{
Session = session;
}
public IEnumerable<T> GetAll()
{
return Session.Query<T>();
}
public T GetByID(int id)
{
return Session.Get<T>(id);
}
public T GetByID(Guid key)
{
return Session.Get<T>(key);
}
public void Save(T entity)
{
Session.Save(entity);
Session.Flush();
}
public void Delete(T entity)
{
Session.Delete(entity);
Session.Flush();
}
}
Check out this solution - https://bitbucket.org/cedricy/cygnus/overview
Its a simple implementation of a Repository pattern that we've used in our production MVC 1, 2, and 3 applications.
Of course, we've learned since then that we really appreciate having our queries run directly against ISession. You have more control over them that way. That and Ayende told us not too.
Thanks Cedric!

Entity Framework 4 update and insert one function

I'm migrating from SubSonic to EF4. In SubSonic models had a function called Save, if the key of the model was 0 an insert was done, otherwise an update.
Is there a way to make a generic Save function like in SubSonic? For exmaple using an extension method?
Yes but you have to do it yourselves. Try something like this:
public interface IEntity
{
int Id { get; set; }
}
...
public void SaveOrUpdate<T>(T entity) where T : IEntity
{
using (var context = new MyContext())
{
if (entity.Id == 0)
{
context.AddObject(entity);
}
else
{
context.Attach(entity);
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
}
context.SaveChanges();
}
}
I think a little bit better version will be
public static void SaveOrUpdate(this T entity) where T : IEntity

Resources