On wrapping ObjectContext with DbContext - asp.net-mvc

I am using EF 6.x with MVC 4 and VS2010.
I am testing an application where I have created database model from existing database, essentially I have added Edmx object to the application. I am at a very early stage of testing Generic Repository and Unity of Work. I have copied / pasted a block of code with some little adjustments from the ASP.NET website but I run into a problem that ObjectContext does not have functions such as Set(), Entry(), Find() etc. I tried to follow this answer on SO and wrap ObjectContext in DbContext:
public class GenericRepository<TEntity> where TEntity : class
{
private DbContext _dbcontext;
private StudentContext _context;
private DbSet<TEntity> _dbSet;
public GenericRepository(StudentContext context)
{
this._context = context;
this._dbcontext = new DbContext(_context, true); // type mismatch of input parameters
this._dbSet = _dbcontext.Set<TEntity>();
}
// ...
}
but compiler does not accept it due to wrong input parameters. _context is derived from ObjectContext. I was surprised because after reading this page I thought the constructor DbContext(ObjectContext objectContext, bool dbContextOwnsObjectContext) can create DbContext object if I provide StudentContext.
What am I missing?

Related

Using Unity.WebForms in ASP.NET

I am trying to implement DI in a webforms project, so I installed the Unity.WebForms dlls in my UI layer. As soon as I did an App_Start folder was created for me with a UnityWebFormsStart class file. Inside this file there is a method RegisterDependencies which asks to be edited.
What is the next step after registering the dependencies? Is there something I need to add in the Global.asax class file? And how and where do I resolve a type inside a webform? Do I decorate that with any attributes?
The Unity.WebForms dll and NuGet package does a few things for you in the background. It will ensure that a child container is started at the begin of each new web request and disposed at the end of each request. This allows you to register components with a 'per web request' lifestyle (using the HierarchicalLifetimeManager in Unity), which is useful for components such as O/RM unit of works such as Entity Framework's DbContext.
The other thing that the package ensures is that the given HttpHandler (usually your Page) and all its child controls are Built up. The BuildUp method is the way to initialize components that are not created by the container itself.
So the idea is to use property injection in your page classes and controls, but solely use constructor injection in ALL other components in your application. Constructor injection is the preferred mechanism for doing dependency injection, but constructor injection is unfortunately not possible in ASP.NET Page and Control classes.
So your page could look like this:
public class CancelOrderPage : Page
{
[Dependency]
public ICommandHandler<CancelOrder> CancelOrderHandler { get; set; }
void CancelButton_Click(object sender, EventArgs e) {
this.CancelOrderHandler.Handle(new CancelOrder {
OrderId = Guid.Parse(this.OrderIdHiddenField.Value)
});
}
}
For the rest of your application, use constructor injection:
public class CancelOrderHandler : ICommandHandler<CancelOrder>
{
private readonly IAuthorizedRepository<Order> orderRepository;
private readonly IEventPublisher eventPublisher;
public CancelOrderHandler(IAuthorizedRepository<Order> orderRepository,
IEventPublisher eventPublisher) {
this.orderRepository = orderRepository;
this.eventPublisher = eventPublisher;
}
public void Handle(CancelOrder command) {
// some implementation
}
}
In the RegisterDependencies you will have to register your dependencies. You can do this manually:
container.RegisterType<ICommandHandler<CancelOrder>, CancelOrderHandler>();
container.RegisterType<IEventPublisher, InProcessPublisher>();
container.RegisterType(
typeof(AuthorizedRepository<>),
typeof(DbContextRepo<>));
Or you can use batch-registration.

MVC 5 Identity 2 - customer UserStore methods not being called

I am trying to implement a custom UserStore for my MVC 5 application so that I can delegate the database commands to my existing database project.
The tables in my database use integer keys, so I created a custom UserManager that inherits UserManager<User, int> instead of just UserManager<User>. For that reason, I also created a custom UserStore that implements IUserPasswordStore<User, int> instead of just IUserPasswordStore<User>.
Briefly:
public class CustomUserManager : UserManager<User, int>
{
public CustomUserManager(CustomUserStore store) : base(store)
{
}
}
public class CustomUserStore : IUserPasswordStore<User, int>
{
private readonly DbContext _db;
public CustomUserStore(DbContext db)
{
_db = db;
}
public Task<User> FindByIdAsync(int userId)
{
return _db.users.SingleOrDefaultAsync(u => u.Id == userId);
}
public Task UpdateAsync(User user)
{
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
return _db.SaveChangesAsync();
}
}
Now, it seems that when I call UpdateAsync on CustomUserManager, it does not go through my custom CustomUserStore, but rather through some default implementation or something. The problem is evident because CustomUserManager.UpdateAsync() returns Task<IdentityResult>, while my implementation in CustomUserStore returns just Task. Hence there are no errors or anything, but the method is not being called. I think IUserPasswordStore<User, int> should have some method UpdateAsync that returns Task<IdentityResult> but it doesn't...
On the other hand, the FindByIdAsync method does work fine and calls the method in my CustomUserStore.
I am quite sure the problem is due to inheriting the classes with the custom key type (int in my case). Any example of a custom UserStore I can find online just uses the string keys and does not inherit IUserStore<User, int> but just IUserStore<User>.
However I can't figure out my problem. Perhaps I can just override all the methods in my CustomUserManager but that seems like a work-around rather than a solution. Is this a bug in the framework perhaps, I think the custom key types is still relatively new or even in alpha?
I know that this is an old question but I struggled yesterday with the same issue and after some time spent on it, I decided to take a look in the Identity source code and what I've found, almost made me smashed my head against the wall...
Simple, if you call UserManager.UpdateAsync, in the base class you will see that before the UserStore.UpdateAsync there is a validation that takes place, which, in my case, failed (doesn't matter the reason). So, please, be so kind and check in your class (controller class) the result of UpdateAsync which is an IdentityResult and more then sure the Succes result is false.
Evdin

How to share the same instance in ASP.NET MVC 5 with Ninject?

I am trying to use Ninject for IoC with ASP.NET MVC 5.
My controller has a constructor like this:
private readonly IUnitOfWork _unit;
private readonly IContactService contactService;
public ContactsController(IUnitOfWork unit, IContactService contactService)
{
this._unit = unit;
this._contactService = contactService;
}
So the ContactService has a constructor (IUnitOfWork unit) and should share the same instance of the IUnitOfWork, but Ninject is giving a new different instance. My ContactService derives of a class with this constructor:
public ServiceBase(IUnitOfWork unit)
{
_unit = unit;
_repository = _unit.GetRepository<TEntity>();
}
My ninject config bindings:
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IContactService>().To<ContactService>().InRequestScope();;
}
I hope that InRequestScope() give the same instance per request, but that is not happening.
I had exactly the same problem now. I had Ninject and Ninject.Web.Common packages installed and I was injecting dependencies using my custom NinjectControllerFactory. Using Erik's response linked by BatteryBackupUnit's in comments, I have decided to uninstall my Ninject packages and I have installed Ninject.MVC5 package.
The package generated a NinjectWebCommon.cs Ninject confgiuration file in the App_Start folder. The only thing you need to do is to copy your bindings to RegisterServices method in NinjectWebCommon.cs file and stop using your custom NinjectControllerFactory (if you have one).
It solved my problem, hope it solves your problem as well.

How to implement UnitOfWork with Onion Architecture without introducing dependencies?

I am setting up an asp.Net Mvc 4 app and looking to configure it using the Onion Architecture Pattern.
In the past I have used the Unit of Work Pattern like this
public class UnitOfWork : IUnitOfWork, IDisposable
{
private IRepository<CallModel> _callRepo;
private IRepository<UserModel> _userRepo;
public IRepository<CallModel> CallRepo
{
get
{
if (_callRepo == null)
{
_callRepo = new Repository<CallModel>();
}
return _callRepo;
}
}
public IRepository<UserModel> UserRepo
{
get
{
if (_userRepo == null)
{
_userRepo = new Repository<UserModel>();
}
return _userRepo;
}
}
}
I would then pass the instance of the UnitOfWork Class to the Controller to do simple CRUD stuff like this.
public class QuestionsController : Controller
{
private IUnitOfWork _unitOfWork;
[Inject]
public QuestionsController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
I have seperated the app into three projects.
Core
Infrastructure
Web
I have my Interfaces all in the Core project and the implementation of the IRepository interface in the Infrastructure project.
If I put the UnitOfWork Class in the Core Project then since it calls for a new Repository in the Infrastructure project I am creating a dependency from the Core to the Infrastructure.
If I include it in the Infrastructure then the Web project (which has the controllers) will have a dependency on the Infrastructure and the whole Solution ends up looking less like an Onion and more like spaghetti.
I have my Interfaces all in the Core project and the implementation of the IRepository interface in the Infrastructure project. If I put the UnitOfWork Class in the Core Project then since it calls for a new Repository in the Infrastructure project I am creating a dependency from the Core to the Infrastructure.
Hmm, not really. Your unit of work class should have a dependency on IRepository, not the Repository implementation itself. If you are using Dependency Injection, this should not pose a problem, as it should find the right type and provide it at runtime. I'm not sure whether the Onion architecture is even possible without using DI.
See david.s's answer as well, as this is exactly how I set things up--have a project for the sole purpose of wiring up dependencies.
What I do is have another project named DependencyResolution which has references to Core and Infrastructure an where I configure my IoC container. Then I can refence only DependencyResolution from the Web project.
I would do like david.s create project named DependencyResolution but let it referance Web, Core and Infrastructure.
In that project you could do:
[assembly: PreApplicationStartMethod(typeof(Start), "Register")]
namespace DependencyResolution
{
public static class Start
{
public static void Register()
{
UnityConfig.Register();
}
}
}
and to register DI.
namespace DependencyResolution
{
public static class UnityConfig
{
public static void Register()
{
DependencyResolver.SetResolver(new UnityDependencyResolver());
}
}
}
So no referance between Web and infrastructure is needed.
Best regards
For what it's still worth, I have implemented my own library that applies the UnitOfWork-pattern a little differently than I've seen in any code sample before, but I have found it to work very well in practice. In short: I kinda copied the way .NET Transactions work by creating a scope and then enlisting resources in the ambient unitofwork(-manager) where necessary. What basically happens is that when a new message/request is being handled, this code is executed:
public void Handle<TMessage>(TMessage message)
{
using (var scope = CreateMessageProcessorContextScope())
{
HandleMessage(message);
scope.Complete();
}
}
Now just as with transactions, as soon as the Thread is still inside the scope, an ambient UnitOfWork-controller is present in which all resources that are used and changed during the request can enlist dynamically. They do this by implementing the IUnitOfWork-interface that has two methods:
public interface IUnitOfWork
{
bool RequiresFlush();
void Flush();
}
Instances that implement this interface can then enlist themselves as follows:
MessageProcessorContext.Current.Enlist(this);
Typically, a Repository-class will implement this interface, and when it detects it's managed aggregates are changed/added/removed, it can enlist itself (double enlistments are ignored).
In my case, the framework assumes that you are using an IOC-framework that will resolve all message-handlers and repositories for you, so I made enlistment to the ambient unit of work controller easier by letting it inject an instance of the current IUnitOfWorkManager into the constructor where required. This way the dependencies of the unit of work manager and the actual pieces that require to be flushed (repositories, services, etc) are reversed:
internal sealed class OrderRepository : IOrderRepository, IUnitOfWork
{
private readonly IUnitOfWorkManager _manager;
private readonly Dictionary<Guid, Order> _orders;
public OrderRepository(IUnitOfWorkManager manager)
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
_manager = manager;
}
bool IUnitOfWork.RequiresFlush()
{
return _orders.Values.Any(order => order.HasChanges());
}
void IUnitOfWork.Flush()
{
// Flush here...
}
public void Add(Order order)
{
_orders.Add(order.Id, order);
_manager.Enlist(this);
}
}
As soon as a request has been handled succesfully (no exceptions thrown), scope.Complete() will be called which triggers the controller to check with all enlisted items whether they (still) need to be flushed (by calling RequiresFlush()), and if so, flushes them (by calling Flush()).
All in all, this allows for a very maintainable solution (in my perspective) in which new repositories and other dependencies can be added on the fly without changing any master unitofwork class, just like the TransactionManager doesn't need to know upfront which items may take part in any given Transaction.

L2S DataContext out of synch: row not found or changed

Psssst...!
Read on, by all means. But I can tell you here that the problem had nothing to do with the DataContext, but with Dependency Injection. I have left the question up, as it documents one possible issue with the "row not found or changed error" that has nothing to do with real world concurrency conflicts.
It seems the problems have been caused by badly written dependency injection. Or rather, I am beginning to believe, by default lifecycle management by the DI container I used.
The problem was that I used a DataContext as a constructor argument that was supplied by Ninject. It seems that the default behaviour was to cache this DataContext, leading to all manner of unexpected behaviour. I will ask a separate question about this.
Anyway, what follows is my original question, which as you will see, misses the real cause of the issue by a mile...
The Problem
I am getting a number of errors that imply that the DataContext, or rather, the way I am using the DataContext is getting out of synch.
The error occurs on db.SubmitChanges() where db is my DataContext instance. The error is:
Row not found or changed.
The problem only occurs intermitently, for example, adding a row then deleting it. If I stop the dev server and restart, the added row is there and I can delete it no problem.
Ie, it seems that the problem is related to the DataContext losing track of the rows that have been added.
IMPORTANT:
Before anyone votes to close this thread, on the basis of it being a duplicate, I have checked the sql server profiler and there is no "Where 0 = 1" in the SQL.
I have also recreated the dbml file, so am satisfied that the database schema is in synch with the schema represented by the dbml file.
Ie, no cases of mismatched nullable/not nullable columns, etc.
My Diagnosis (for what it is worth):
The problem seems (to me) related to how I am using the DataContext. I am new to MVC, Repositories and Services patterns, so suspect that I have wired things up wrong.
The Setup
Simple eLearning app in its early stages. Pupils need to be able to add and delete courses (Courses table) to their UserCourses.
To do this, I have a service that gets a specific DataContext instance Dependency Injected into its constructor.
Service Class Constructor:
public class SqlPupilBlockService : IPupilBlockService
{
DataContext db;
public SqlPupilBlockService(DataContext db)
{
this.db = db;
CoursesRepository = new SqlRepository<Course>(db);
UserCoursesRepository = new SqlRepository<UserCourse>(db);
}
// Etc, etc
}
The CoursesRepository and UserCoursesRepository are both private properties of the service class that are of type IRepository (just a simple generic repository interface).
SqlRepository Code:
public class SqlRepository<T> : IRepository<T> where T : class
{
DataContext db;
public SqlRepository(DataContext db)
{
this.db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
db.SubmitChanges();
}
#endregion
}
The two methods for adding and deleting UserCourses are:
Service Methods for Adding and Deleting UserCourses:
public void AddUserCourse(int courseId)
{
UserCourse uc = new UserCourse();
uc.IdCourse = courseId;
uc.IdUser = UserId;
uc.DateCreated = DateTime.Now;
uc.DateAmended = DateTime.Now;
uc.Role = "Pupil";
uc.CourseNotes = string.Empty;
uc.ActiveStepIndex = 0;
UserCoursesRepository.Add(uc);
UserCoursesRepository.Save();
}
public void DeleteUserCourse(int courseId)
{
var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
UserCoursesRepository.Delete(uc);
UserCoursesRepository.Save();
}
Ajax
I am using Ajax via Ajax.BeginForm
I don't think that is relevant.
ASP.NET MVC 3
I am using mvc3, but don't think that is relevant: the errors are related to model code.
The problem only occurs intermitently,
for example, adding a row then
deleting it. If I stop the dev server
and restart, the added row is there
and I can delete it no problem.
Your code does not show what the link is between the Added Row and the Delete/Update. Your Add() doesn't return an object reference.
I'm thinking you are missing a Refresh (ie reload the object after Insert). Is your IdCourse also the PK in the Table?
Edit:
Further research has revealed that the problem is with the dependency injection.
The problem was related to how Dependency Injection manages the items it creates. Google for 'lifecycle management' in IoC or DI. Essentially, DI cached a DataContext constructor argument that I injected.
For a way to solve this using the Factory Pattern, see this thread:
Ninject caching an injected DataContext? Lifecycle Management?
The accepted answer solved it all.

Resources