I'm using the repository pattern with a context and ninject as the IOC. I have a service which handles getting and setting page properties in the database.
public class MyContext : DbContext
{
public MyContext() : base ("DefaultConnection")
{
}
public DbSet<PageProperty> PageProperties { get; set; }
public DbSet<Contact> Contacts { get; set; }
}
public class DefaultRepository : IRepository
{
MyContext _context;
public DefaultRepository(MyContext context)
{
_context = context;
}
public IQueryable<PageProperty> PageProperties { get { return _context.PageProperties; } }
public IQueryable<Contact> Contacts { get { return _context.Contacts; } }
}
public class ModuleLoader : NinjectModule
{
public ModuleLoader()
{
}
public override void Load()
{
var context = new MyContext();
context.Database.Initialize(false);
Bind<MyContext>().ToConstant(context).InSingletonScope();
Bind<IRepository>().To<DefaultRepository>();
Bind<IPagePropertyProvider>().To<DefaultPagePropertyProvider>().InSingletonScope();
}
}
public class DefaultPagePropertyProvider : IPagePropertyProvider
{
IRepository _repository;
object _syncLock = new object();
public DefaultPagePropertyProvider (IRepository repository)
{
_repository = repository;
}
public string GetValue(string pageName, string propertyName
{
lock (_syncLock)
{
var prop = page.PageProperties.FirstOrDefault(x => x.Property.Equals(propertyName) && x.PageName.Equals(pageName)).Value;
return prop;
}
}
public void SetValue(string pageName, string propertyName, string value)
{
var pageProp = _repository.PageProperties.FirstOrDefault(x => x.Property.Equals(propertyName) && x.PageName.Equals(pageName));
pageProp.Value = value;
_repository.SaveSingleEntity(pageProp);
}
}
In my view I am doing 3 ajax calls, one to get a list from contacts to fill out a table, one ajax call to determine how many pages i have depending on the page size I'm using, and one ajax call to set the page size that I want to use. so a select box changes the page size (How many contacts per page: [ 30]) , a table that displays the contacts (generated from jquery which decifers json), and finally a div containing a list of page numbers to click. The workflow is, call GetContacts(), this function then queries the PageProperties to find out the page size to use, then call GetPages(), this function also queries PageProperties to find out what page size to use, SetPageSize() which sets the page size. So GetContacts() and GetPages() is used when a page is selected from the div, SetPageSize() then GetContacts() and GetPages() is called when the select box change event is fired. GetContacts() and GetPages() is only called when the first SetPageSize() $.ajax request is done() and there is a success from that function.
Now, before I added lock(syncLock) in the DefaultPageProperty service and before I added InSingletonScope to both that service and the context, I was getting two errors.
The connection was not closed. The connection's current state is connecting.
An EdmType cannot be mapped to CLR classes multiple times
I assumed because the connection was in a connecting state, that the context was being reused and reused and reused, so I thought putting that to SingletonScope() would mean that only one connection was made, then I thought the same about DefaultPageProperty and then because I was making async calls to that service, I should put a lock over the database querying.
It works, and the problems don't exist. But I don't know if what I have done is correct within the pattern I'm using, I'm wondering if I've missed something fundamental? My question is, is this a proper/viable solution which won't create any caveats later down the road? Have I actually solved the issue or just created more?
I redesigned the way I do my context now.
I have my context then I implement IDbContextFactory<TContext> called DefaultContextFactory<MyContext> and I inject them.
In the Repository I have in the public constructor _context = contextFactory.Create();.
Then throughout the repository i just use _context.WhatEver() and its fine.
I also did in the ModuleLoader Bind<IRepository>().To<DefaultRepository>().InTransientScope() in order to make every call to it create a new repository!
I don't need a repository factory because I only have one repository!
Related
Question:
Why does passing a list from a protected internal class to an API method and then back to my UI take 4 seconds when direct data access in Entity takes .4? Is it due to the actual passing of the list through these methods?
Background:
I wish to create an "API" layer that sits between my data access layer using Entity Framework and my UI layer. The idea is to limit access to the CRUD operations and force everything through the API however I'm noticing terrible performance.
When I use my class structure here, the get method in this case takes 4 seconds to run:
public class API
{
DataAccessClass _dataAccess = new DataAccessClass();
public List<Items> GetById(int id)
{
return _dataAccess.Get(id);
}
protected internal class DataAccessClass
{
protected internal List<Items> GET(int id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
protected internal List<Items> GET(long id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
}
}
However when I use my dbcontext directly in code (which I want to prevent), it runs in .4 seconds using the same code found in the protected class above:
using (var context = dbcontext)
{
return context.GetItems();
}
EDIT:
When I exclude the data access portion of the API which is the protected internal portion, and run the using statement in the API directly (just cutting out the protected internal portion) then I get the acceptable .4 seconds.
To solve my performance issue, I removed overloads from the GET class above.
My performance issues from the original question where resolved by changing method names on two of my get methods (one that took an int and one long). Not sure why these overloads causes issues but by removing the overloads and specifying names directly, my issue with performance was resolved.
My working class looks like:
public class API
{
DataAccessClass _dataAccess = new DataAccessClass();
public List<Items> GetById(int id)
{
return _dataAccess.Get(id);
}
protected internal class DataAccessClass
{
protected internal List<Items> GetByInt(int id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
protected internal List<Items> GetByLong(long id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
}
}
I've been banging my head with this for days and still can't decide on which is the correct approach.
This question is targeting WPF specifically since as opposed to a web-application, many posts and articles online recommends a context per view-model approach and not a context per request.
I have a WPF MVVM application which is using an Entity-Framework DB first model.
here is an example of two models used in my app (created by EF Designer):
public partial class User
{
public User()
{
this.Role = new HashSet<Role>();
}
public string ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Role { get; set; }
}
public class Role
{
public Role()
{
this.User = new HashSet<User>();
}
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<User> User { get; set; }
}
I've narrowed my options on how to handle this to the following:
1) Creating a DataAccess class which creates and disposes of the DbContext on each method call:
public class Dal
{
public User GetUserById(object userId)
{
using (var db = new DbEntities())
{
return db.User.Find(userId);
db.SaveChanges();
}
}
public void RemoveUser(User userToRemove)
{
using (var db = new DbEntities())
{
db.User.Remove(userToRemove);
db.SaveChanges();
}
}
}
which I can use in my ViewModel as follows:
public class UserManagerViewModel : ObservableObject
{
private readonly Dal dal = new Dal();
// models...
//commands...
}
2) Similar to approach 1 but without the Using statements:
public class Dal : IDisposable
{
private readonly DbEntities db = new DbEntities();
public User GetUserById(object userId)
{
return db.User.Find(userId);
db.SaveChanges();
}
public void RemoveUser(User userToRemove)
{
db.User.Remove(userToRemove);
db.SaveChanges();
}
public void Dispose()
{
db.SaveChanges();
}
}
The use is the same inside the ViewModel
3) Create a repository for each entity. Looks the same as the above options (also has the with or without the using dilemma), however every repository contains only methods related to its entity.
Afaik the use is the same as above inside my ViewModel.
4) Create a Unit-Of-Work class that will pass the appropriateRepository on demand:
public class UnitOfWork : IDisposable
{
private DbEntities db = new DbEntities();
private IUserRepository userRepository;
public IUserRepository UserRepository
{
get
{
return userRepository ?? new UsersRepository(db);
}
}
public void Save()
{
db.SaveChanges();
}
public void Dispose()
{
db.Dispose();
}
}
and use it inside my ViewModel as follows:
public class UserManagerViewModel : ObservableObject
{
private readonly UnitOfWork unit = new UnitOfWork();
// models...
//commands...
}
Which of the above approach (if any) is preferred in terms of in terms of data concurrency, better abstraction and layering and overall performance?
EDIT - Found the following paragraph in this article. :
When working with Windows Presentation Foundation (WPF) or Windows Forms, use a context instance per form. This lets you use change-tracking functionality that context provides.
However, it raises the question of whether I should create a DbContext object in my view-model or is it better to have a utility class such as my DAL class and reference it.
This is what dependency injection frameworks are designed to solve. Yes, it's yet another technology to add to your project, but once you start using DI you never look back.
The real problem here is that you're trying to make this decision in your view models when you really should be employing inversion of control and making the decision higher up. A WPF/MVVM application will want a context per-form so that changes are only submitted once a user is finished editing, and also to give the user the opportunity to cancel the changes. I know you're not using this in a web application but a well-designed architecture means you should be able to, in which case you'll want a context per request. You may want to write a console-app utility that populates the database with static data, in this case you may want a global/singleton context for performance and ease-of-use. Lastly, your unit tests also need to mock the context, probably on a per-test basis. All four of these cases should be set up in your injection framework and your view models should neither know or care about any of them.
Here's an example. I personally use Ninject, which is specifically designed for .NET. I also prefer NHibernate, although the choice of ORM is irrelevant here. I have session objects that have different scoping requirements, and this gets set up in a Ninject module that initializes my ORM classes:
var sessionBinding = Bind<ISession>().ToMethod(ctx =>
{
var session = ctx.Kernel.Get<INHibernateSessionFactoryBuilder>()
.GetSessionFactory()
.OpenSession();
return session;
});
if (this.SingleSession)
sessionBinding.InSingletonScope();
else if (this.WebSession)
sessionBinding.InRequestScope();
else
sessionBinding.InScope(ScreenScope);
This sets up the scoping for an ISession, which is the NHibernate equivalent of your context class. My repository classes, which manage the database objects in memory, contain a reference to the session they are associated with:
public class RepositoryManager : IRepositoryManager
{
[Inject]
public ISession Session { get; set; }
... etc...
{
The [Inject] attribute tells Ninject to populate this field automatically using the scoping rules I've set up. So far this is all happening in my domain classes, but it extends to my view model layer as well. In my scoping rules I pass in an object called "ScreenScope", and while I won't go into it here it basically means that any time I ask for a session object in my ScreenViewModel, or any view models that it has as members (including their own children) the same ISession object gets automatically created and passed in to all of them. By using DI scoping I don't even have to think about it, I just declare the members with the [Inject] attribute and it happens:
public class ScreenViewModel
{
[Inject] public CustomerService CustomerService { get; set; }
[Inject] public SalesService SalesService { get; set; }
[Inject] public BillService BillService { get; set; }
...etc...
}
These service classes all contains a RepositoryManager that has been injected, and since they're all in ScreenViewModel the ISession object will be the same, at least in my WPF build. if I switch to my MVC build they're the same for all view models created for a given request, and if I switch to a console build it uses the same ISession for everything in the entire program.
TL;DR: Use dependency injection and a scope your contexts to one-per-form.
In my earlier usage of MVVM within WPF I was utilising an open context per VM but I quickly ran into issues with thread safety of DBContexts once applications evolved to make better use of Async.
Whilst there is a greater development overhead, I now utilise dependency injection to provide a DBContextFactory (not the DBContext itself). I spin up a context in a using statement witihn the VM to fill observableCollections with plinq calls via EF. Another performance benefit of this method is running queries with AsNoTracking(). The annoying part is managing the reattachment of new or modified objects to the short lived context:
shortDBContext.Attach(myEntity).State = EntityState.Added; // or modified
await shortDBContext.SaveChangesAsync();
I have a settings record that some of the fields get maintained via the admin panel. However, I am implementing an import for data, and need to track the last time an import occurs. So I added that field to my settings record and created a controller that imports the data. Now, my question is, how can I update the settings? I have created a service, but don't know how to force orchard to save the values.
public class BmobileSettingsService : IBmobileSettingsService
{
IOrchardServices _svc;
public BmobileSettingsService(IOrchardServices svc)
{
_svc = svc
}
public BmobileSettingsPart Get()
{
return _svc.WorkContext.CurrentSite.As<BmobileSettingsPart>();
}
public void Save(BmobileSettingsPart part)
{
/// how do I save the data?
}
Here is the code I used when using a repository:
public class BmobileSettingsService : IBmobileSettingsService
{
IOrchardServices _svc;
IRepository<BmobileSettingsPartRecord> _repository;
public BmobileSettingsService(IOrchardServices svc,IRepository<BmobileSettingsPartRecord> repository)
{
_svc = svc;
_repository = repository;
}
public BmobileSettingsPartRecord Get()
{
return _repository.Table.FirstOrDefault();
//return _svc.WorkContext.CurrentSite.As<BmobileSettingsPart>();
}
public void Save(BmobileSettingsPartRecord part)
{
_repository.Update(part);
_repository.Flush();
}
}
Here is the call to thye service:
// update the last imported date
var rec = _bmobileSettings.Get();
rec.LastImageSyncDate = DateTime.Today;
_bmobileSettings.Save(rec);
The data just does not get persisted to the database.
I believe the question has actually been answered in the comment by Bertrand Le Roy.
I don't think you need to actually force anything.
This is an example for allowing users to register using Orchard 1.8:
var site = _siteService.GetSiteSettings();
var regsettings = site.As<RegistrationSettingsPart>();
regsettings.UsersCanRegister = true;
There is no method you need to call after setting the value.
That being said, if you have a reccord for your part you could possibly use an IRepository and call update on it. There have been bugs in older versions of Orchard where calling Update on an IRepository can force an update. However this should not be required and may merit a bug report if you're using the latest version of Orchard.
I am using the repository and unit of work patterns and dependency injection to access the database with entity framework 5 in my web application. I have a User class from which Entity Framework generates a Code-First database.
public class User
{
public Guid UserId { get; set; }
public string UserName { get; set; }
.
.
.
public string LanguagePreference { get; set; }
public virtual List<Role> Roles { get; set; }
public virtual List<Branch> Branches { get; set; }
}
I have a UserService class that is used to Add or Update users. This class takes an IUserUnitOfWork as a parameter in the constructor and Unity injects a UserUnitOfwork. The IUserUserOfWork contains an IRepository<User>, an IRepository<Location> and an IRepository<Role>. These are set as Repository<T> by the DI bootstrapper. The IUserUnitOfWork sets up the different Repositories with the same entity framework DbContext. I did this as I was having issues updating the many-to-many relationships related to the User (Locations and Roles).
UserUnitOfWork:
public IRepository<Branch> BranchRepository {get; set;}
public IRepository<Role> RoleRepository { get; set; }
public IRepository<User> UserRepository { get; set; }
public DbContext Context { get; set; }
public UserUnitOfWork(DbContext context, ITransientErrorDetectionStrategy errorDetectionStrategy,RetryStrategy retryStrategy )
{
Context = context;
BranchRepository = new Repository<Branch>(context, errorDetectionStrategy, retryStrategy);
RoleRepository = new Repository<Role>(context, errorDetectionStrategy, retryStrategy);
UserRepository = new Repository<User>(context, errorDetectionStrategy, retryStrategy);
}
The Repository class then uses Entity Framework 5 to access the database.
Example of method from Repository.FirstOrDefault:
public virtual T FirstOrDefault(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
{
T result = null;
_retryPolicy.ExecuteAction(() =>
{
IQueryable<T> entities = GetHelper(filter, orderBy, includeProperties);
result = entities.FirstOrDefault();
});
return result;
}
And Update from Repository:
public virtual void Update(T entity)
{
if (_dbContext.Entry(entity).State == System.Data.EntityState.Detached)
{
_dbContext.Set<T>().Attach(entity);
_dbContext.Entry(entity).State = System.Data.EntityState.Modified;
}
}
So my problem now is that when I update the User it correctly updates the data in the database, and when I log out and log in the initial change works. However if I update again and log out and in the new change isn't picked up even though the database is updated.
I'm beginning to fear that the approach I've taken is incorrect, can someone tell me how to make sure that when I do an update Entity Framework will always get the latest version?
EDIT:
So I've created a Per Request Lifetime Manager like so:
public class PerHttpRequestLifetimeManager : LifetimeManager
{
private readonly object key = new object();
public override object GetValue()
{
if (HttpContext.Current != null &&
HttpContext.Current.Items.Contains(key))
return HttpContext.Current.Items[key];
else
return null;
}
public override void RemoveValue()
{
if (HttpContext.Current != null)
HttpContext.Current.Items.Remove(key);
}
public override void SetValue(object newValue)
{
if (HttpContext.Current != null)
HttpContext.Current.Items[key] = newValue;
}
}
In my DI bootstrapper I now setup my domain context like below:
container.RegisterType<DbContext, DomainContext>(new PerHttpRequestLifetimeManager());
It still doesn't appear to be working, am I missing something else or am I setting it up incorrectly?
EDIT 2:
Just to point out the architecture:
We have an MVC application which uses Angular JS to make ajax calls to a Web Api service layer. The Web Api has an ISomethingService injected into it. It is this ISomethingService that has the repositories injected into it. Would there be some confusion for the PerHttpRequestLifetimeManager since there is both an MVC and Web API project running?
EDIT 3:
An example of how I am saving the edited user:
We have a UserModel class that is used for communications between the ServiceLayer -> API -> UI layer and back. The User class is the one generated by Entity Framework code first. The EditUser method in the UserService takes in a UserModel.
I then user the _unitOfWork.UserRepository to get the corresponding database user
var editedUser = _unitOfWork.UserRepository.FirstOrDefault(x => x.UserId == userModel.UserId);
I map the fields from the userModel to the editedUser and I then call (in the UserService)
_unitOfWork.UserRepository.Update(editedUser)
and after
_unitOfWork.Save()
YET ANOTHER EDIT:
So I have edited a simple method that updates a single text field on the user table (Language Preference). I explicitly call the dispose method after the update to ensure I am disposing the method.
public void SetUserLanguagePreference(Guid userId, string language)
{
var user = _unitOfWork.UserRepository.FirstOrDefault(x => x.UserId == userId);
user.LanguagePreference = language;
_unitOfWork.UserRepository.Update(user);
_unitOfWork.Save();
_unitOfWork.Dispose();
}
UnitOfWork.Dispose() calls the dispose method of the repositories and the Dbcontext
The database updates correctly. However the behaviour is still incorrect. When I log out and in first it retrieves the correct value. When I change it again and log out and in again it doesn't update. This has been the pattern before, it get the first update after I log out and in, but if I change again and log out and in it doesn't pick it up.
Finally, not an edit but an answer! We use Claims based authentication and have a class that overrides the ClaimsPrinciple Authenticate method that is called whenever a user is authenticated.
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal.Identity.IsAuthenticated)
{
//Check here if the authenticated user has access to this system
//using the user repository and if so add more claims to the token
}
return base.Authenticate(resourceName, incomingPrincipal);
}
It was not possible to inject into this method using DI as it always went to the empty constructor (not sure why but that's the way it is).
So instead we were setting the repository in the empty constructor like so:
public PRAuthenticationManager()
{
_userRepository = DiBootstrapper.Container.Resolve<IRepository<User>>();
}
When the Authenticate method is called we check our database for a user with the claims attached to the ClaimsPrincipal. If we make a match we add new claims to the token which are then used for each call to the Web Api later. This repository was not being disposed (even if all the others were) and so when a user logged out and in they got data from that same context which had not been disposed from the last time the user logged in.
Three full days trying to find that one....
See if this helps: How do I get Entity Framework 5 to update stale data
I ran into the same problem, it doesn't refresh from the database if you already have the object in your ObjectContext, of course, this would only work on a per object basis, but that might be just what you need.
I want to have ASP.NET MVC website that would have some frontend for looking into, adding and other things with data. And then I want to have Web Api for getting data for mobile devices and so. I want to use code first from EF (and I am using Ninject). I create classes for hotel and others. I created HotelManagerContext and database is created and looks good. I am adding data by HomeController and by Repository for this. When I looked at database in Visual Studio data are there. But when I tried to use my HotelsController for Api datacontext is empty. What's wrong? What I forget to set? Something with connection string or what?
This is my ApiController:
public class HotelsController : ApiController
{
private IHotelRepository _hotelRepo { get; set; }
public HotelsController(IHotelRepository repo)
{
_hotelRepo = repo;
}
// GET api/Hotels
public IEnumerable<Hotel> GetHotels()
{
return _hotelRepo.GetAll();
}
// GET api/Hotels/5
public Hotel Gethotel(int id)
{
return _hotelRepo.Get(id);
}
}
This is part of my controller for frontend:
public class HomeController : Controller
{
private IHotelRepository _hotelRepo { get; set; }
public HomeController(IHotelRepository repo)
{
_hotelRepo = repo;
}
public ActionResult Index()
{
return View();
}
// next methods, for adding data and so
}
This is my repository:
public class HotelRepository : IHotelRepository
{
private HotelManagerContext db { get; set; }
public HotelRepository()
:this (new HotelManagerContext())
{
}
public HotelRepository(HotelManagerContext hotelManagerContext)
{
// TODO: Complete member initialization
this.db = hotelManagerContext;
}
public Models.Hotel Get(int id)
{
return db.hotels.SingleOrDefault(h => h.hotId == id);
}
public IQueryable<Models.Hotel> GetAll()
{
return db.hotels;
}
public Hotel Add(Hotel hotel)
{
db.hotels.Add(hotel);
db.SaveChanges();
return hotel;
}
}
This is my HotelManagerContext:
public class HotelManagerContext : DbContext
{
public HotelManagerContext() : base("name=HotelManagerContext")
{
}
public DbSet<Hotel> hotels { get; set; }
}
Edit:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IHotelRepository>().To<HotelRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
}
Edit2:
Here is my connection string:
<add name="HotelManagerContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=HotelManagerContext-20121219191411; Integrated Security=True; MultipleActiveResultSets=True; AttachDbFilename=|DataDirectory|HotelManagerContext-20121219191411.mdf" providerName="System.Data.SqlClient" />
And I just found that even in HomeController I have empty datacontext. So when I check content of database in Server Explorer there are data which I added (in HomeController). But everytime when I have request page (web api or frontend) datacontext is empty and I can add items there are counting from zero but in database there are already next but can't get it. It's really weird.
What does your connection string look like? "name=HotelManagerContext" seems incomplete. I think you would want to also explicitly specify providerName="System.Data.EntityClient" at the very least (see here). In any case, it is common practice to put the connection string in the Web.Config file and assign the name there (i.e. name="HotelMamangerContext") then, under normal circumstances, EF will just discover the connection string by convention as long as the name of your DbContext class matches the name of the connection string in Web.Config (otherwise you can still specify it explicitly in the constructor).
On a different note (I don't think this should be related to you current problem), you could consider injecting you DbContext as well. Then you could drop the parameter-less constructor on your repository class unless you need to keep it around for another reason such as unit testing. Also, if you are using Ninject.Web.Common, you may want to consider scoping the instances to the request level (see InRequestScope).
...
kernel.Bind<HotelMamangerContext>().ToSelf().InRequestScope();
kernel.Bind<IHotelRepository>().To<HotelRepository>().InRequestScope();
...
I can't find solution for this so I create new project and I did everything like in the question. I have same classes, copy and paste code frome question. I can't find any important difference but second time it's working.
I know this isn't exactly solution but in this case I could start my project from begging so I tried it and it really helps. Just don't know where is problem.