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
Related
I'm using MVC3 and currently i'm following a practice such that I declare one instance of DB Container for every controller. I use that container instance for every request coming to that controller. If I need to go to my models for a query or sth, I send that instance as a parameter to the model's function. So for the whole application, I create and use 4-5 different instances of DB Container class. My question is, does this have a good or bad effect on my database operations? Does it matter to create a seperate container instance? What is the proper way to use container classes?
I believe the mentioned class was called DBContext before.
I am not sure it is what you mean but I can give you an example of an approach I'm following rather often:
Create a sort of 'domainservice class' for the DBContext
public class MyDomainService : IDisposable
{
private MyDbEntities dbo;
private bool isDisposed;
public MyDomainService()
{
dbo = new MyDbEntities();
}
public User GetUser(string userName)
{
return (from usr in dbo.Users
where usr.UserName == userName
select usr).SingleOrDefault();
}
public void Dispose()
{
if (isDisposed)
return;
isDisposed = true;
dbo.Dispose();
}
}
Create a custom Controller class that extends Controller or AsyncController
and override the Initialize and Dispose methods:
public class MyController : Controller
{
protected MyDomainService DomainService { get; private set; }
protected override void Initialize(System.Web.Routing.RequestContext
requestContext)
{
base.Initialize(requestContext);
DomainService = new MyDomainService();
}
protected override void Dispose(bool disposing)
{
DomainService.Dispose();
base.Dispose(disposing);
}
}
Now you can use the following approach in per example the HomeController inheriting MyController
public class HomeController : MyController
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string username)
{
var user = DomainService.GetUser(username);
if (user != null)
return RedirectToAction("Account", "Information");
return View();
}
}
This will keep your controllers rather clean.
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();
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.
I am Using Moq package for testing a Controller.
HomeController.cs
public class HomeController : Controller
{ readonly IPermitRepository _repository;
public HomeController(IPermitRepository rep)
{ this._repository = rep; }
public ViewResult Index()
{
ViewBag.Message = "Hello World";
PermitModel model = _repository.GetPermitDetails();
return View(model);
}
}
In HomeControllerTest.cs
[TestClass]
Public class HomeControllerTest
{
[TestMethod]
public void Index()
{
var messagingService = new Mock<IPermitRepository>();
var controller = new HomeController(messagingService.Object);
var result = controller.Index() as ViewResult;
Assert.IsInstanceOfType(result.Model, typeof(PermitModel));
}
}
But its giving error.
Assert.IsInstanceOfType failed. Expected type:. Actual type:<(null)>.
Can some one provide solution and also some inf about Moq package in MVC3.
Thanks in advance
Moq returns null by default for each non void method call.
So when in your controller you call _repository.GetPermitDetails(); it return null that's why your test fails.
You need to call Setup on your method to return something:
var messagingService = new Mock<IPermitRepository>();
messagingService.Setup(m => m.GetPermitDetails()).Returns(new PermitModel());
var controller = new HomeController(messagingService.Object);
You can find more info in the Moq quickstart on how to customize the mock behaviour.
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