EntityException occurred in EntityFramework.SqlServer.dll - asp.net

My Controller code
ParaEntities db = new ParaEntities();
public List<Client> GetAllClients()
{
return db.Client.ToList();
}
Please click this link to see the error message
It is weird that when I am first time to click the button to get all client information then it responses 500. In the second time, I click the button to get all client, which is success.

You should assign variable and display the data in View.
Please change the syntax as i write below.
ParaEntities db = new ParaEntities();
public List<Client> GetAllClients()
{
var getData= db.Client.ToList();
if(getData==null)
{
return null;
}
return getData;
}

This error points to a connection problem rather then code issue. Check that the connectionstring is valid and that the user specified in the connectionstring has access to the database. If you're running the application on IIS then make sure that the applicationpool user has access to the database. Here is another SO issue were they solved this error.
If you want to store the db context as a local variable in your controller class then I suggest you to instantiate it inside of the controllers constructor. Then you make sure that every time a instance of the controller is created then a new db context is created as well.
Lets say your controller namned ClientController
private ParaEntities db;
public ClientController()
{
this.db = new ParaEntities();
}
public List<Client> GetAllClients()
{
return db.Client.ToList();
}
Another approach is to wrap your db context in a using statment inside of your method. In that case you make sure that the method is using a fresh context when being called upon and that the context is being disposed when the operation is completed.
public List<Client> GetAllClients()
{
using(ParaEntities db = new ParaEntities())
{
return db.Client.ToList();
}
}
PS: both examples violates the dependency inversion principle (hard coupling to the db context) but thats for another day

Please try this
public List<Client> GetAllClients()
{
ParaEntities db = new ParaEntities();
return db.Client.ToList();
}

Related

Using Unity Dependency Injection in Multi-User Web Application: Second User to Log In Causes First User To See Second User's Data

I'm trying to implement a web application using ASP.NET MVC and the Microsoft Unity DI framework. The application needs to support multiple user sessions at the same time, each of them with their own connection to a separate database (but all users using the same DbContext; the database schemas are identical, it's just the data that is different).
Upon a user's log-in, I register the necessary type mappings to the application's Unity container, using a session-based lifetime manager that I found in another question here.
My container is initialized like this:
// Global.asax.cs
public static UnityContainer CurrentUnityContainer { get; set; }
protected void Application_Start()
{
// ...other code...
CurrentUnityContainer = UnityConfig.Initialize();
// misc services - nothing data access related, apart from the fact that they all depend on IRepository<ClientContext>
UnityConfig.RegisterComponents(CurrentUnityContainer);
}
// UnityConfig.cs
public static UnityContainer Initialize()
{
UnityContainer container = new UnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
return container;
}
This is the code that's called upon logging in:
// UserController.cs
UnityConfig.RegisterUserDataAccess(MvcApplication.CurrentUnityContainer, UserData.Get(model.AzureUID).CurrentDatabase);
// UnityConfig.cs
public static void RegisterUserDataAccess(IUnityContainer container, string databaseName)
{
container.AddExtension(new DataAccessDependencies(databaseName));
}
// DataAccessDependencies.cs
public class DataAccessDependencies : UnityContainerExtension
{
private readonly string _databaseName;
public DataAccessDependencies(string databaseName)
{
_databaseName = databaseName;
}
protected override void Initialize()
{
IConfigurationBuilder configurationBuilder = Container.Resolve<IConfigurationBuilder>();
Container.RegisterType<ClientContext>(new SessionLifetimeManager(), new InjectionConstructor(configurationBuilder.GetConnectionString(_databaseName)));
Container.RegisterType<IRepository<ClientContext>, RepositoryService<ClientContext>>(new SessionLifetimeManager());
}
}
// SessionLifetimeManager.cs
public class SessionLifetimeManager : LifetimeManager
{
private readonly string _key = Guid.NewGuid().ToString();
public override void RemoveValue(ILifetimeContainer container = null)
{
HttpContext.Current.Session.Remove(_key);
}
public override void SetValue(object newValue, ILifetimeContainer container = null)
{
HttpContext.Current.Session[_key] = newValue;
}
public override object GetValue(ILifetimeContainer container = null)
{
return HttpContext.Current.Session[_key];
}
protected override LifetimeManager OnCreateLifetimeManager()
{
return new SessionLifetimeManager();
}
}
This works fine as long as only one user is logged in at a time. The data is fetched properly, the dashboards work as expected, and everything's just peachy keen.
Then, as soon as a second user logs in, disaster strikes.
The last user to have prompted a call to RegisterUserDataAccess seems to always have "priority"; their data is displayed on the dashboard, and nothing else. Whether this is initiated by a log-in, or through a database access selection in my web application that calls the same method to re-route the user's connection to another database they have permission to access, the last one to draw always imposes their data on all other users of the web application. If I understand correctly, this is a problem the SessionLifetimeManager was supposed to solve - unfortunately, I really can't seem to get it to work.
I sincerely doubt that a simple and common use-case like this - multiple users logged into an MVC application who each are supposed to access their own, separate data - is beyond the abilities of Unity, so obviously, I must be doing something very wrong here. Having spent most of my day searching through depths of the internet I wasn't even sure truly existed, I must, unfortunately, now realize that I am at a total and utter loss here.
Has anyone dealt with this issue before? Has anyone dealt with this use-case before, and if yes, can anyone tell me how to change my approach to make this a little less headache-inducing? I am utterly desperate at this point and am considering rewriting my entire data access methodology just to make it work - not the healthiest mindset for clean and maintainable code.
Many thanks.
the issue seems to originate from your registration call, when registering the same type multiple times with unity, the last registration call wins, in this case, that will be data access object for whoever user logs-in last. Unity will take that as the default registration, and will create instances that have the connection to that user's database.
The SessionLifetimeManager is there to make sure you get only one instance of the objects you resolve under one session.
One option to solve this is to use named registration syntax to register the data-access types under a key that maps to the logged-in user (could be the database name), and on the resolve side, retrieve this user key, and use it resolve the corresponding data access implementation for the user
Thank you, Mohammed. Your answer has put me on the right track - I ended up finally solving this using a RepositoryFactory which is instantiated in an InjectionFactory during registration and returns a repository that always wraps around a ClientContext pointing to the currently logged on user's currently selected database.
// DataAccessDependencies.cs
protected override void Initialize()
{
IConfigurationBuilder configurationBuilder = Container.Resolve<IConfigurationBuilder>();
Container.RegisterType<IRepository<ClientContext>>(new InjectionFactory(c => {
ClientRepositoryFactory repositoryFactory = new ClientRepositoryFactory(configurationBuilder);
return repositoryFactory.GetRepository();
}));
}
// ClientRepositoryFactory.cs
public class ClientRepositoryFactory : IRepositoryFactory<RepositoryService<ClientContext>>
{
private readonly IConfigurationBuilder _configurationBuilder;
public ClientRepositoryFactory(IConfigurationBuilder configurationBuilder)
{
_configurationBuilder = configurationBuilder;
}
public RepositoryService<ClientContext> GetRepository()
{
var connectionString = _configurationBuilder.GetConnectionString(UserData.Current.CurrentPermission);
ClientContext ctx = new ClientContext(connectionString);
RepositoryService<ClientContext> repository = new RepositoryService<ClientContext>(ctx);
return repository;
}
}
// UserData.cs (multiton-singleton-hybrid)
public static UserData Current
{
get
{
var currentAADUID = (string)(HttpContext.Current.Session["currentAADUID"]);
return Get(currentAADUID);
}
}
public static UserData Get(string AADUID)
{
UserData instance;
lock(_instances)
{
if(!_instances.TryGetValue(AADUID, out instance))
{
throw new UserDataNotInitializedException();
}
}
return instance;
}
public static UserData Current
{
get
{
var currentAADUID = (string)(HttpContext.Current.Session["currentAADUID"]);
return Get(currentAADUID);
}
}
public static UserData Get(string AADUID)
{
UserData instance;
lock(_instances)
{
if(!_instances.TryGetValue(AADUID, out instance))
{
throw new UserDataNotInitializedException();
}
}
return instance;
}

Unit Test UserManager<IdentityUser> in asp.net core

My application is an ASP.NET Core 1.0 Web API. I would like to test the following method (snipped):
public async Task<bool> GetClientsAsync()
{
foreach (var user in await this.clientAdapter.Users().ToListAsync())
{
return true;
}
return false;
}
Normally the clientAdapter is calling UserManager<IdentityUser>'s property Users. So the code for the "real" clientAdapterlooks like that:
public IQueryable<IdentityUser> Users()
{
return this.userManager.Users;
}
Now when I am testing the clientAdapter looks like the following:
private readonly List<IdentityUser> clientList;
public TestClientAdapter(){
this.clientList= this.CreateClientList();
}
public IQueryable<IdentityUser> Users()
{
return this.userList.AsQueryable();
}
The return type of the method Users() has to be IQueryable<IdentityUser> since thats the return value of the original class UserManager<IdentityUser>. Now if I execute the test I am getting the following error, as soon as it hit's the foreach loop (the problem is the ToListAsync() call):
System.NotSupportedException: "Store does not implement IQueryableUserStore<TUser>."
If I change the loop from
foreach (var user in await this.clientAdapter.Users().ToListAsync())
{
return true;
}
to
foreach (var user in this.clientAdapter.Users().ToList())
{
return true;
}
Everything works fine.
My Problem:
I am not not able to mock the UserManager since the UserManager needs a UserStore which needs a DBContext which I dont know how to mock. And even if it was possbile to mock the DBContext, I think this would turn my unit test into an integration test and I dont want that. Plus it's probably not worth the effort. So I cannot just work with a mocked Usermanager and get the data from it.
My Question:
Is it possible to make the unit test pass, without changing the method I want to test?
EDIT
#CodeCaster:
The injected clientAdapter now looks like the following (snipped):
public class TestClientAdapter: IClientAdapter, IQueryableUserStore<IdentityUser>
{
private readonly List<IdentityUser> clientList
private UserManager<IdentityUser> testUserManager;
public TestClientAdapter: ()
{
clientList= this.CreateclientList();
this.testUserManager = new UserManager<IdentityUser>(this, null, null, null, null, null, null, null, null);
}
public IQueryable<IdentityUser> Users()
{
return this.testUserManager.Users;
}
IQueryable<IdentityUser> IQueryableUserStore<IdentityUser>.Users
{
get
{
return this.clientList.AsQueryable();
}
}
Now Iam getting another Exception:
"System.InvalidOperationException" in System.Private.CoreLib.ni.dll"
ToListAsync (among of other async methods like AnyAsync, etc.) is not a standard Linq2SQL (aka IQueryable<T>) extension method from System.Linq.*.
It's part of EntityFramework and as such it assumes certain preconditions, hence it can't work with a queryable List. Basically it's a wrapper around query.AsAsyncEnumerable() and AsAsyncEnumerable checks for the existence of IAsyncEnumerable<TSource> and/or IAsyncEnumerableAccessor<TSource> and if not there throws the invalid operation exception.
There are two things you can do...
Use EF Core InMemoryDatabase for an integration test, which was made for integration tests
Refactor your code so IQueryable<T> doesn't leak outside of your repository or command/query handlers
Technically it may be possible to create an list which implements AsAsyncEnumerable<T> but I haven't tried it and most likely not working with list.AsQueryable() since it wraps the list somewhere below...
Let the clientAdapter you inject for tests also implement IQueryableUserStore<TUser>, as the UserManager casts it to that, and if that fails, throws the mentioned exception.

ASP.NET, thread and connection-string stored in Session

My application can connect with multiple data bases (every data base have the same schema), I store the current DB, selected by user, in Session and encapsule access using a static property like:
public class DataBase
{
public static string CurrentDB
{
get
{
return HttpContext.Current.Session["CurrentDB"].ToString();
}
set
{
HttpContext.Current.Session["CurrentDB"] = value;
}
}
}
Other pieces of code access the static CurrentDB to determine what DB use.
Some actions start background process in a thread and it need access the CurrentDB to do some stuff. I'm thinking using something like this:
[ThreadStatic]
private static string _threadSafeCurrentDB;
public static string CurrentDB
{
get
{
if (HttpContext.Current == null)
return _threadSafeCurrentDB;
return HttpContext.Current.Session["CurrentDB"].ToString();
}
set
{
if (HttpContext.Current == null)
_threadSafeCurrentDB = value;
else
HttpContext.Current.Session["CurrentDB"] = value;
}
}
And start thread like:
public class MyThread
{
private string _currentDB;
private thread _thread;
public MyThread (string currentDB)
{
_currentDB = currentDB;
_thread = new Thread(DoWork);
}
public DoWork ()
{
DataBase.CurrentDB = _currentDB;
... //Do the work
}
}
This is a bad practice?
Actually, I think you should be able to determine which thread uses which database, so I would create a class inherited from Thread, but aware of the database it uses. It should have a getDB() method, so, if you need a new Thread which will use the same database as used in another specific Thread, you can use it. You should be able to setDB(db) of a Thread as well.
In the session you are using a current DB approach, which assumes that there is a single current DB. If this assumption describes the truth, then you can leave it as it is and update it whenever a new current DB is being used. If you have to use several databases in the same time, then you might want to have a Dictionary of databases, where the Value would be the DB and the Key would be some kind of code which would have a sematic meaning which you could use to be able to determine which instance is needed where.

Remember Values Asp.Net

This is my controller code:
private string testVal;
public ActionResult Index()
{
testVal = "test";
return View();
}
public ActionResult NextView()
{
if (testVal == null)
Debug.WriteLine("testVal is null");
return View();
}
Is it possible to remeber values like testVal after changing page? It seems that when redirecting it resets values (testVal in NextVal is null).
Edit:
I try to save values to session but Session is null. I am using SignalR and when user is connected to page i use static event from hub to inform controller that user has connected - but inside method that runs on that event Session is unfortunetly null.
My controller code:
public ActionResult Index()
{
LoadingHub.userConnected += new EventHandler<IdEventArgs>(UserConnected);
return View();
}
private void UserConnected(object sender, IdEventArgs e)
{
Debug.WriteLine("User Connected with Id: " + e.Id);
if (Session == null)
Debug.WriteLine("Session is null");
}
My signalr hub:
public class LoadingHub : Hub
{
public static event EventHandler<IdEventArgs> userConnected;
//Function informs server that user has connected
public void Connected()
{
Debug.WriteLine("Hub Connected Method");
var id = Context.ConnectionId;
userConnected(this, new IdEventArgs(id));
}
}
Every time that you make a request a new instance of the controller is created so using a private field you will not be able to retain the value of this variable.
The easiest way for you to retain it it is to use a session. (if you want to retain this value per user base)
for example in your code
public ActionResult Index()
{
System.Web.HttpContext.Current.Session["testVal"] = "test";
return View();
}
public ActionResult NextView()
{
if (System.Web.HttpContext.Current.Session["testVal"] == null)
Debug.WriteLine("testVal is null");
return View();
}
you can use cookie or cache to replace the variable.
when you redirect to a webpage ,the controller will be newed ,so you cannot get the right testVal .but the cookie is stored in broswer .so you can set it and get .
You may use session or Pass the data to the controller
Have you looked into ASP.NET server side state management click here.
These are basically different ways to remember a value on the server once a new page has been loaded.
So a few server side techniques you could use to remember testVal are Session State or Application State. However Session State is more suitable for your scenario as it is only specific to the user's current session whereas Application State stores data that can be shared between sessions and would therefore be more ideal for global variables.
You can read the link I provided to read more on the differences though.
I would also like to warn you (as some say to use cookies), the user can delete or disable or manipulate them on the browser so this isn't an ideal solution.

NHibernate crashes when being called from a web user control in ASP.Net

I have a very strange problem: NHibernate crashes when being called from a web user control.
I am working on a ASP.Net (2.0) web page which uses NHibernate to access a database.
And I have a simple factory class to access a column CurrentStepNumber in the table ProjectInfo:
public class ProjectEntity
{
private int? _currentStepNumber;
public virtual int? CurrentStepNumber
{
get { return _currentStepNumber; }
set { _currentStepNumber = value; }
}
public static ProjectWizardEntity GetById(int id, bool shouldLock)
{
return RepositoryFactory.ProjectWizardRepository.GetById(id, shouldLock);
}
public static ProjectWizardEntity GetById(int id)
{
return GetById(id, false);
}
public virtual void Save()
{
RepositoryFactory.ProjectWizardRepository.Save(this);
}
public virtual void SaveOrUpdate()
{
RepositoryFactory.ProjectWizardRepository.SaveOrUpdate(this);
}
}
This class is accessed via a proxy class, so that everytime a new value is assigned it is flushed to the database:
public class DBHelper
{
ProjectEntity _projectEntity;
ProjectEntity GetProjectEntity()
{
if (_projectEntity == null)
_projectEntity = //get or create a new one;
return _projectEntity ;
}
public int? CurrentStepNumber
{
get
{
return (CurrentProjectId > 0) ? CurrentProjectWizardEntity.CurrentStepNumber : 0;
}
set
{
if (CurrentProjectId > 0)
{
CurrentProjectWizardEntity.CurrentStepNumber = value;
CurrentProjectWizardEntity.SaveOrUpdate();
}
}
}
}
Now the problem:
When I access CurrentStepNumber from the test.aspx page, everything works perfectly
When I read this field from the web user control (test.ascx) which is used on test.aspx page it is still OK
However when I try to assign a value to CurrentStepNumber in the code behind the control (test.ascx) I always get an exception:
NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
Actually SaveOrUpdate method of the NHibernate Repository throws the exception.
I could not figure out what could be the problem here, so any help will be appreciated.
I think that You have a session management problem here. How is RepositoryFactory.ProjectWizardRepository.GetById creating and possibly disposing the NHibernate session? Does it create and then close a session?
It seems that DBHelper.GetProjectEntity() is creating or loading a ProjectEntity. Later, when CurrentStepNumber's setter i called, You insert or update the object to the database.
The problem is that when DBHelper.GetProjectEntity() is loading an existing object and later closing the session after it has been loaded but keep the object around, we are entering deep water. When the object is later updated, You set a new value for CurrentStepNumber and send the object to NHibernate to save. The problem here is that the object is not associated with the new session that is created and closed during saving. Nhibernate then gets confused since a new object is discovered that is not loaded from current session but it has an id of an existing object.
For a solution, Google for "NHibernate asp.net session management" and You will get a number of good hits about how to use the ASP.NET request cycle as a unit of work.

Resources