Creating a DataContext with LinqToSql - Could Storing Collection in Class Result in Memory Issues? - asp.net-mvc

I've ran into some problems in an application where the .net process is running out of memory. One change I made in the application has been adding a lot of Linq to Sql classes. I'm wondering if there is an issue on how I'm creating my DataContext.
I could create my datacontext by creating the datacontext when I need it. Obviously if I was changing data, I would create a variable and hold the datacontext, because I would need the same data context in multiple statements.
Technique 1
public class SchoolRepository
{
DataBaseDataContext GetCtx()
{
return new DataBaseDataContext();
}
public List<School> GetSchools()
{
return GetCtx().Schools.ToList();
}
}
Here is another way I could create the DataContext. In this case I have a class field which holds a reference to a DataContext.
Technique 2:
public class SchoolRepository
{
private DataBaseDataContext _ctx = null;
DataBaseDataContext ctx
{
get { return _ctx = (_ctx ?? new DataBaseDataContext()); }
}
public List<School> GetSchools()
{
return ctx.Schools.ToList();
}
}
I have been using the second way (with a class variable), and I'm wondering if that could be causing the context to stick around longer than the first way--- because it would stick around as long as an instance of my class stuck around.
Perhaps I'm grasping at straws here-- but I'm wondering if one way is "safer" than the other way.

Related

How to use a Session provider in a DI project

I am developing a web application in ASP.NET MVC5.
Like all basic web applications it also has a login page where a user can authenticate himself. Once authenticated I want to store a couple of user-related items in the Session so I don't have to query the database every time to reconstruct the authenticated user.
After having read Mark Seemann's book about Dependency Injection I want to loosely couple all my layers and make sure that everything can easily be replaced.
At the moment my SessionProvider is by default using the Session object, but maybe in the future this could change to another type of storage mechanism.
The approach I have taken is by using Ambient Context which he explained with the TimeProvider example, but I am wondering if this is the right approach for this functionality and if it is thread safe (also for unit testing).
Is my solution proper or how would you implement such a mechanism? This has been in my head for days now so who can help me define the best solution?
Thanks!
public abstract class SessionProvider
{
private static SessionProvider _current;
static SessionProvider()
{
_current = new DefaultSessionProvider();
}
public static SessionProvider Current
{
get { return _current; }
set
{
if (value == null)
{
throw new ArgumentNullException();
}
_current = value;
}
}
public abstract string UserName { get; set; }
}
My local default:
public class DefaultSessionProvider : SessionProvider
{
public override string UserName
{
get { return (string) HttpContext.Current.Session["username"]; }
set { HttpContext.Current.Session["username"] = value; }
}
}
So I have access in my entire solution to my SessionProvider, whether this is a real session object or a database-driven storage mechanism...
SessionProvider.Current.UserName = "myUserName";
Once authenticated I want to store a couple of user-related items in
the Session so I don't have to query the database every time to
reconstruct the authenticated user.
Well, it looks like you're working on some sort of caching mechanism. It doesn't really matter if it's in a Session or in Redis cache, or any other type of cache. And this cache is key-value storage. I would create cache interface, something like that:
interface ICache
{
object this[string key] {get; set;}
}
And create concrete classes. SessionCache in your case:
public SessionCache : ICache
{
private IHttpSessionState _session;
public SessionCache(IHttpSessionState session)
{
_session = session;
}
// ICache implementation goes here...
}
So you'll narrow down the problem to dependency-inject Session object to concrete class (SessionCache). With Ninject you can do something like:
.WithConstructorArgument("session",ninjectContext=>HttpContext.Session);
And after that you can finally make your controllers dependent on ICache.
In your unit tests project you can create another ICache concrete class, something like DummyCache with in-memory cache. So you can test your controllers without sticking to Session object.

"Proper" MVC - Should I be using a constructor or not?

If I have a model that works directly with my database (Personally using ASP.NET w\Entity Framework) should I be using a constructor to set variable?
Example:
public class songs
{
public IEnumerable<songs> allSongs {get; }
public songs()
{
using (var context = new entities())
{
allSongs = context.songs.orderBy(n => n.name).toList();
}
}
}
VS
public class songs
{
public IEnumerable<songs> allSongs
{
get
{
using (var context = new entities())
{
allSongs = context.songs.orderBy(n => n.name).toList();
}
}
}
public songs() {}
}
Technically both are correct, but which is more correct? The only time I can think of where there is only one correct answer is if the variable I'm setting either needs to always be updated or stay the same during an operation.
You shouldn't be accessing the data from a domain class.
You should create a SongRepository which interacts with your database. You inject the controller with this repository and when you want a list of songs you simply refer to that repository.
It might become a little tricky when songs is actually supposed to be it's own entity. However I'd strongly suggest you to implement the repository pattern.
The second approach is best when working with repositories.
Example layout:
public class SongController : Controller {
private SongRepository _songRepository;
public SongController(SongRepository repo) {
_songRepository = repo;
}
public ActionResult ShowSongs(){
return View(_songRepository.GetAllSongs());
}
}
public class SongRepository {
public IEnumerable<Song> GetAllSongs(){
using (var context = new entities())
{
allSongs = context.songs.orderBy(n => n.name).toList();
}
}
}
What if you only want to get 1 song? I'm sure you don't want to load all songs then.
If I may add, you should take a look around at existing projects or tutorials to see how things can be done. Note that I say can, what you'll read is by no means the way to do it. For example, #JeroenVannevel recommends the repository pattern, but there are plenty of people who recommend against it (when working with EF).
I recommend browsing the top questions in entity-framework, entity-framework-4, entity-framework-5 and entity-framework-6 before deciding on your data access strategy.

Storing context object in Request object, is it disposed of?

I am writing a MVC3 application, using NInject DI and repository pattern. Ninject is set up so that the repositories have a per-request lifetime.
I am putting the context object into the Http Request object, using the following code:
public static MessengerEntities GetContext()
{
if (!HttpContext.Current.Items.Contains("_db_context"))
{
HttpContext.Current.Items.Add("_db_context", new MessengerEntities());
}
return (MessengerEntities)HttpContext.Current.Items["_db_context"];
}
Then each repository calls this procedure to get either an existing or a new context object, e.g.:
public class TestRepository : ITestRepository
{
private MessengerEntities context = ContextHelper.GetContext();
#region ITestRepository Members
private string _testProperty = "blah";
public string testProperty
{
get
{
_testProperty = context.UserLogins.Where(n => n.inactive == null || !n.inactive.Value).ToList().Count.ToString();
return _testProperty;
}
set
{
_testProperty = value;
}
}
#endregion
}
(Later on, I plan to use a generic IRepository pattern, but for now I am just using this test repository.)
My question is: when the Request object is disposed of, will it also dispose of the context object in the Items collection? In other words, will it call Dispose on each object that may be stored in that collection?
I know there are a lot of discussions about this issue here, but they all seem to involve scenarios that are not quite the same as mine, so it's kind of hard to divine the answer.

Mocking DbContext.Set<T>()?

We're using EF Code first, and have a data context for our sales database. Additionally, we have a class that sits on top of our data context and does some basic CRUD operations.
For example, we have the following function:
public static T Create<T>(int userId, T entity) where T : class, IAllowCreate
{
if (entity == null)
throw new ArgumentNullException("entity");
using (SalesContext dc = new SalesContext())
{
dc.Set<T>().Add(entity);
dc.SaveChanges();
return entity;
}
}
I found an example of how to create fake contexts and IDBset properties. I started implementing that, but I ran in to an issue.
We use dc.Set() quite liberally (as seen above) in our code, as we attempt to create generic CRUD methods. Instead of having a ReadCustomer, ReadContact etc, we would just do Read(). However, dc.Set returns a DbSet, not an IDbSet, so I'm not able to mock that.
Has anyone been able to mock or fake DbContext and still use the Set functionality?
interface ISalesContext
{
IDbSet<T> GetIDbSet<T>();
}
class SalesContext : DbContext, ISalesContext
{
public IDbSet<T> GetIDbSet<T>()
{
return Set<T>();
}
}
I used a different name, but you can use the new operator if you prefer to hide the regular implementation.

Session variables in ASP.NET MVC

I am writing a web application that will allow a user to browse to multiple web pages within the website making certain requests. All information that the user inputs will be stored in an object that I created. The problem is that I need this object to be accessed from any part of the website and I don't really know the best way to accomplish this. I know that one solution is to use session variables but I don't know how to use them in asp .net MVC. And where would I declare a session variable? Is there any other way?
I would think you'll want to think about if things really belong in a session state. This is something I find myself doing every now and then and it's a nice strongly typed approach to the whole thing but you should be careful when putting things in the session context. Not everything should be there just because it belongs to some user.
in global.asax hook the OnSessionStart event
void OnSessionStart(...)
{
HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}
From anywhere in code where the HttpContext.Current property != null you can retrive that object. I do this with an extension method.
public static MySessionObject GetMySessionObject(this HttpContext current)
{
return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}
This way you can in code
void OnLoad(...)
{
var sessionObj = HttpContext.Current.GetMySessionObject();
// do something with 'sessionObj'
}
The answer here is correct, I however struggled to implement it in an ASP.NET MVC 3 app. I wanted to access a Session object in a controller and couldn't figure out why I kept on getting a "Instance not set to an instance of an Object error". What I noticed is that in a controller when I tried to access the session by doing the following, I kept on getting that error. This is due to the fact that this.HttpContext is part of the Controller object.
this.Session["blah"]
// or
this.HttpContext.Session["blah"]
However, what I wanted was the HttpContext that's part of the System.Web namespace because this is the one the Answer above suggests to use in Global.asax.cs. So I had to explicitly do the following:
System.Web.HttpContext.Current.Session["blah"]
this helped me, not sure if I did anything that isn't M.O. around here, but I hope it helps someone!
Because I dislike seeing "HTTPContext.Current.Session" about the place, I use a singleton pattern to access session variables, it gives you an easy to access strongly typed bag of data.
[Serializable]
public sealed class SessionSingleton
{
#region Singleton
private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";
private SessionSingleton()
{
}
public static SessionSingleton Current
{
get
{
if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
{
HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
}
return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
}
}
#endregion
public string SessionVariable { get; set; }
public string SessionVariable2 { get; set; }
// ...
then you can access your data from anywhere:
SessionSingleton.Current.SessionVariable = "Hello, World!";
Well, IMHO..
never reference a Session inside your view/master page
minimize your useage of Session. MVC provides TempData obj for this, which is basically a Session that lives for a single trip to the server.
With regards to #1, I have a strongly typed Master View which has a property to access whatever the Session object represents....in my instance the stongly typed Master View is generic which gives me some flexibility with regards to strongly typed View Pages
ViewMasterPage<AdminViewModel>
AdminViewModel
{
SomeImportantObjectThatWasInSession ImportantObject
}
AdminViewModel<TModel> : AdminViewModel where TModel : class
{
TModel Content
}
and then...
ViewPage<AdminViewModel<U>>
If you are using asp.net mvc, here is a simple way to access the session.
From a Controller:
{Controller}.ControllerContext.HttpContext.Session["{name}"]
From a View:
<%=Session["{name}"] %>
This is definitely not the best way to access your session variables, but it is a direct route. So use it with caution (preferably during rapid prototyping), and use a Wrapper/Container and OnSessionStart when it becomes appropriate.
HTH
Although I don't know about asp.net mvc, but this is what we should do in a normal .net website. It should work for asp.net mvc also.
YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}
You would put this inside a method for easy access.
HTH
There are 3 ways to do it.
You can directly access HttpContext.Current.Session
You can Mock HttpContextBase
Create a extension method for HttpContextBase
I prefer 3rd way.This link is good reference.
Get/Set HttpContext Session Methods in BaseController vs Mocking HttpContextBase to create Get/Set methods
My way of accessing sessions is to write a helper class which encapsulates the various field names and their types. I hope this example helps:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;
namespace dmkp
{
/// <summary>
/// Encapsulates the session state
/// </summary>
public sealed class LoginInfo
{
private HttpSessionState _session;
public LoginInfo(HttpSessionState session)
{
this._session = session;
}
public string Username
{
get { return (this._session["Username"] ?? string.Empty).ToString(); }
set { this._session["Username"] = value; }
}
public string FullName
{
get { return (this._session["FullName"] ?? string.Empty).ToString(); }
set { this._session["FullName"] = value; }
}
public int ID
{
get { return Convert.ToInt32((this._session["UID"] ?? -1)); }
set { this._session["UID"] = value; }
}
public UserAccess AccessLevel
{
get { return (UserAccess)(this._session["AccessLevel"]); }
set { this._session["AccessLevel"] = value; }
}
}
}
Great answers from the guys but I would caution you against always relying on the Session. It is quick and easy to do so, and of course would work but would not be great in all cicrumstances.
For example if you run into a scenario where your hosting doesn't allow session use, or if you are on a web farm, or in the example of a shared SharePoint application.
If you wanted a different solution you could look at using an IOC Container such as Castle Windsor, creating a provider class as a wrapper and then keeping one instance of your class using the per request or session lifestyle depending on your requirements.
The IOC would ensure that the same instance is returned each time.
More complicated yes, if you need a simple solution just use the session.
Here are some implementation examples below out of interest.
Using this method you could create a provider class along the lines of:
public class CustomClassProvider : ICustomClassProvider
{
public CustomClassProvider(CustomClass customClass)
{
CustomClass = customClass;
}
public string CustomClass { get; private set; }
}
And register it something like:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ICustomClassProvider>().UsingFactoryMethod(
() => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
}
You can use ViewModelBase as base class for all models , this class will take care of pulling data from session
class ViewModelBase
{
public User CurrentUser
{
get { return System.Web.HttpContext.Current.Session["user"] as User };
set
{
System.Web.HttpContext.Current.Session["user"]=value;
}
}
}
You can write a extention method on HttpContextBase to deal with session data
T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null)
{
if(context.Session[key]!=null)
{
return (T) context.Session[key];
}
else if(getFromSource!=null)
{
var value = getFromSource();
context.Session[key]=value;
return value;
}
else
return null;
}
Use this like below in controller
User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db });
The second argument is optional it will be used fill session data for that key when value is not present in session.

Resources