ASP.NET Repository Pattern/Service Layer Caching - asp.net

I'm beginning to work on the caching infrastructure for my ASP.NET MVC site. The problem is, I can't seem to find a reasonable place for data caching (other than 'everywhere')
Right now my architecture looks like this:
Controller -> Service Layer -> Repository. The repository uses Linq to SQL for data access.
The repository exposes generic methods like Insert, GetById, and GetQueryable, which returns an IQueryable that the service layer can further refine.
I like the idea of putting caching in the repository layer, since the service layer shouldn't really care where the data comes from. The problem though is with cache invalidation. The service layer has more information about when data becomes stale than the repository. For instance:
Suppose we have a Users table and an Orders table (the canonical example). The service layer offers methods like GetOrder(int id), which would call the repository layer:
public Order GetOrder(int id)
{
using(var repo = _repoFactory.Create<Order>())
{
return repo.GetById(id)
}
}
or
repo.GetQueryable(order => order.Id == id && order.HasShipped == false).Single();
If we cache in the repository layer, it seems like it would be very limited in knowing when that order data has changed. Suppose the user was deleted, causing all their orders to be deleted with a CASCADE. The service layer could invalidate the Orders cache, since it knew the user was just removed. The repository though (since it's a Unit of Work), wouldn't be aware. (Ignore the fact that we shouldn't be querying orders for a deleted user, since it's just an example).
There's other situations where I think this shows itself. Suppose we want to fetch all the users orders:
repo.GetQueryable(order => order.UserId == userId).ToList()
The repository can cache the results of this query, but, if another order is added, this query is no longer valid. Only the service layer is aware of this though.
It's also possible my understanding of the repository layer is wrong. I sort of view it as a facade around the data source (i.e. changing from L2SQL to EF to whatever, the service layer is unaware of the underlying source).

Realistically, you will need another layer; the data caching layer. It will be used by your service layer when requesting data. Upon such a request, it will decide if it has the data in cache or if it needs to query the appropriate repository. Likewise, your service layer can tell this new data caching layer of an invalidation (the deletion of a particular user, etc.).
What this can mean for your architecture though, is that your data caching layer will implement the same interface(s) your repositories do. A fairly simple implementation would cache the data by entity type and key. However, if you are using a more sophisticated ORM behind the scenes (NHibernate, EF 4, etc.), it should have caching as an option for you.

You could put an event on the objects returned by your repositories, and have the repository subscribe the cache invalidation to a handler.
For example,
public class SomethingRepository{
public Something GetById(int id){
var something = _table.Single(x=>x.id==id);
something.DataChanged += this.InvalidateCache;
return something;
}
public void InvalidateCache(object sender, EventArgs e){
// invalidate your cache
}
}
And your Something object needs to have a DataChanged event and some public method for your service layer to call to trigger it. Like,
public class Something{
private int _id;
public int Id{
get { return _id; }
set {
if( _id != value )
{
_id = value;
OnDataChanged();
}
}
}
public event EventHandler DataChanged;
public void OnDataChanged(){
if(DataChanged!=null)
DataChanged(this, EventArgs.Empty);
}
}
So, all your service layer needs to know is that the data is being changed, and the repository handles the cache invalidation.
I also suggest you take ventaur's advice and put the cache invalidation logic in a separate service. You don't need to go so far as to create a separate "data caching layer", but the logic would be cleaner if kept in a different class.

Related

Autofac Multi-tenant IoC Container in an ASP.NET Web API Application

Autofac 3.0 will have a MultitenantIntegration support and its preview release is out now. To try it out, I created an ASP.NET Web API application with the following configuration:
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {
var config = GlobalConfiguration.Configuration;
config.Routes.MapHttpRoute("Default", "api/{controller}");
RegisterDependencies(config);
}
public void RegisterDependencies(HttpConfiguration config) {
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// creates a logger instance per tenant
builder.RegisterType<LoggerService>().As<ILoggerService>().InstancePerTenant();
var mtc = new MultitenantContainer(
new RequestParameterTenantIdentificationStrategy("tenant"),
builder.Build());
config.DependencyResolver = new AutofacWebApiDependencyResolver(mtc);
}
}
It gets the job done and creates a LoggerService instance as ILoggerService per tenant. I have two problems at this stage which I wasn't able to solve:
I used out of the box provided RequestParameterTenantIdentificationStrategy here as the TenantIdentificationStrategy just for this demo application. I am able to create my custom TenantIdentificationStrategy by implementing ITenantIdentificationStrategy interface. However, TryIdentifyTenant method of the ITenantIdentificationStrategy makes you rely on a static instance such as HttpContext.Current which is something that I don't want in an ASP.NET Web API environment as I want my API to be hosting agnostic (I know that I can delegate this work to the hosting layer but I would rather not to). Is there another way to achieve this in a way that I won't rely on a static instance?
I also have a chance to register tenant specific instance as below:
mtc.ConfigureTenant("tenant1", cb => cb.RegisterType<Foo>()
.As<IFoo>().InstancePerApiRequest());
However, one of my situations requires me to pass the tenant name through the constructor parameter and I would love to have something like below:
mtc.ConfigureTenant((cb, tenantName) => cb.RegisterType<Foo>()
.As<IFoo>()
.WithParameter("tenantName", tenantName)
.InstancePerApiRequest());
Currently there is no such an API. Is there another way to achieve this or this kind of requirement doesn't make any sense?
Multitenant support has been available for a long time, it's just that 3.0 is the first time we've had a NuGet package for it. :)
The RequestParameterTenantIdentificationStrategy is, as documented, just a very simple example showing one possible (and not recommended) way to identify tenant. You will have to choose for yourself how to identify your tenant based on the operating context. It could be from a web.config value, an environment variable, or some other thing in the current environment. If you don't want to use HttpContext.Current, don't. It's up to you to pick where you get that info from.
(A note on the RPTIStrategy - the part that isn't recommended is using a querystring or request parameter as the tenant ID mechanism. I use HttpContext in my production apps and it works fine. There's only so much you can abstract out before you have to actually touch the bare metal.)
There is no way out of the box to provide the lambda registration syntax you're asking for, primarily because tenant is not passed through the resolution process. The resolution process is:
Identify the tenant with the strategy.
Find the tenant's configured lifetime scope.
Use standard Autofac Resolve style syntax.
It's intentionally simple and analogous to the existing operations. At the time of resolve, the sub-lifetime-scope belonging to the tenant is tagged with the tenant ID but the resolution operation doesn't know about the tenant ID... so the lambda wouldn't work (and probably won't anytime soon because it'd change the fundamental internals of the way Autofac works if it did).
To accomplish what you're looking for, you can use a combination of the InstancePerTenant extension when registering...
var builder = new ContainerBuilder();
builder.RegisterType<Foo>().As<IFoo>().InstancePerTenant();
...and registering the ITenantIdentificationStrategy as a dependency in your container.
builder.Register(myIdStrategy).As<ITenantIdentificationStrategy>();
Then make your class take an ITenantIdentificationStrategy rather than the tenant ID directly. Use the strategy to get the tenant ID instead.
If you REALLY want to get fancy, you could register a keyed lambda that resolves the ID strategy, then gets the tenant ID. Then you could add a parameter registration to the object like you did but using a keyed service. (I'm going to go by memory now, so you'll have to double-check my syntax here, but it'll be something like this...)
builder.Register(c =>
{ var s = c.Resolve<ITenantIdentificationStrategy>();
object id;
s.TryIdentifyTenant(out id);
return id;
}).Keyed<object>("tenantId");
builder.RegisterType<Foo>()
.As<IFoo>()
.WithParameter(
(pi, c) => pi.Name == "tenantId",
(pi, c) => c.ResolveKeyed<object>("tenantId"))
.InstancePerApiRequest();
Again, you'll want to double-check me on that, but I'm pretty sure that (or a minor variation) should work to get you what you want.

Usage of repository between EF model and code consumer

I have binary data in my database that I'll have to convert to bitmap at some point. I was thinking whether or not it's appropriate to use a repository and do it there. My consumer, which is a presentation layer, will use this repository. For example:
// This is a class I created for modeling the item as is.
public class RealItem
{
public string Name { get; set; }
public Bitmap Image { get; set; }
}
public abstract class BaseRepository
{
//using Unity (http://unity.codeplex.com) to inject the dependancy of entity context.
[Dependency]
public Context { get; set; }
}
public calss ItemRepository : BaseRepository
{
public List<Items> Select()
{
IEnumerable<Items> items = from item in Context.Items select item;
List<RealItem> lst = new List<RealItem>();
foreach(itm in items)
{
MemoryStream stream = new MemoryStream(itm.Image);
Bitmap image = (Bitmap)Image.FromStream(stream);
RealItem ritem = new RealItem{ Name=item.Name, Image=image };
lst.Add(ritem);
}
return lst;
}
}
Is this a correct way to use the repository pattern? I'm learning this pattern and I've seen a lot of examples online that are using a repository but when I looked at their source code... for example:
public IQueryable<object> Select
{
return from q in base.Context.MyItems select q;
}
as you can see almost no behavior is added to the system by their approach except for hidding the data access query, so I was confused that maybe repository is something else and I got it all wrong. At the end there should be extra benifits of using them right?
Update: as it turned out you don't need repositories if there is nothing more to be done on data before sending them out, but wait! no abstraction on LINQ query? that way client has to provide the query statements for us which can be a little unsafe and hard to validate, so maybe the repository is also providing an abstraction on data queries? if this is true then having a repository is always an essential need in project architecture!! however this abstraction can be provided by using SQL stored procedures. what is the choice if both options are available?
Yes, that's the correct way: the repository contract serves the application needs, dealing ony with application objects.
The (bad)example you are seeing most of the time couples any repository implementation to IQueryable which may or may be not implemented by the underlying orm and after all it is an implementation detail.
The difference between IQueryable and IEnumerable is important when dealing with remote data, but that's what the repository does in the first place: it hides the fact you're dealing with a storage which can be remote. For the app, the repository is just a local collection of objects.
Update
The repository abstracts the persistence access, it makes the application decoupled from a particular persistence implementation and masks itself as a simple collection. This means the app doesn't know about Linq2Sql, Sql or the type of RDBMS used, if any. The app sends/receives objects from the repo, while the repo actually persists or loads objects. The app doesn't care how the repo does it.
I consider the repository a very useful pattern and I'm using it in every project, precisely because it marks the boundry between the application (as the place where problems and solutions are defined and handled) and storage/persistence where data is saved.
You can make you repository a generic one and can get mode value out of it. And make sure you are using an Interface (IItemRepository ) to access repositories in manager layer so that the you can replace your repositories with some another data access method using new repository implementation. Here is an good example how to do this.

Best Way to Write an Asp.Net Web Service To Play Well In the Wild

I am writing an API for my ASP.NET application that other developers will use. The API will basically return a list of people with their first name, last name, and id. There are lots of ways to write web services in ASP.NET, the easiest probably being create a web service function (asmx) that returns a DataTable. This is simple enough for other .NET developers to deal with, but I am not convinced that this is the best way to write a web service for general platform and language independence.
What is the currently accepted standard to write a web service like this that plays well in the wild today?
Some ideas that come to mind from experience:
Use WCF, not .asmx. WCF does all the same things that ASMX files do, and is generally the replacement for ASMX services (see here and here).
Write methods using simple POCO data types, like List<Person> rather than DataTable. Basic types serialize more easily and will make more sense in other programming environments since you want your service to be language independent.
Provide generic CRUD methods for managing data. Depending on how your service will be consumed, if the user needs to modify data, a simple method is to provide getBlah(), updateBlah(obj newObj), deleteBlah(obj objToDelete), etc. that use the same data types.
Hide the details that the service consumer doesn't need to know, rather than just blindly exposing all of your data types, structures, and field names as-is. This will make your service more robust for handling internal changes, and you can simplify and control what the end-users see. For instance, if you have a Person class with 30 properties, and only 5 are relevant to the end-user, provide a class that interfaces between Person and a PersonSimple class which is exposed. Without this layer, your end-users will have to modify your code every time you change your data structure, and you will be locked down by this tight coupling.
If security is important
Execute your service over SSL. This protects data transfered over the wire from being sniffed.
Use authentication, either with a Login method and session, or SOAP headers. Services by default are anonymous unless there is some sort of authentication scheme. Even if you think nobody will find your service because you only provide the URL to your users, it will get out somehow, somewhere, and people will try to misuse the service when it does. Plus, you can control who can do what by different logins and authorization schemes.
I am currently working on a similar issue: A web api service in .NET that receives data tables as input parameters, apply some operations on them (using Table Valued Functions), and return some output data tables.
In your case, you don't need to use a complex class like DataTable; you could use an array (List<>) of a simple class with fields like first name, last name and id. Using Web Api of ASP.NET you could do something like the following:
1) Create a new WebApi project in Visual Studio: For example (in VS 2012) C# > Web > ASP.NET MVC 4 Web Application > select "Wep Api" as project template
You will see a VS project with lots of folders, including one named Models
For help see: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
2) Create a new model code file Person.cs with a class like the following:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string[] Friends { get; set; }
}
3) Create e new controller code file PersonController.cs with methods for getting, inserting and updating records of the database. All the necessary serialization/deserialization (JSON and XML) and data binding is done automatically by the Web Api environment set by the project template.
// Get all the records of persons
public IList<Person> Get()
{
// read database into a list of persons (List<Person>)
// return List<Person>
}
Return record of a selected person:
public Person Get(int id)
{
// read database for a selected person
}
Parameter binding (reading a JSON/XML content sent by http POST into an object, or into a list objects) is also done automatically, as easy as the following:
// parameter binding: Create a Person object with content from XML/JSON
public void ReadPerson(Person p)
{
Trace.WriteLine(Person.Id);
}
public void ReadPersonList(List<Person> plist)
{
Trace.WriteLine(plist.Count);
}

Entity Framework ObjectContext re-usage

I'm learning EF now and have a question regarding the ObjectContext:
Should I create instance of ObjectContext for every query (function) when I access the database?
Or it's better to create it once (singleton) and reuse it?
Before EF I was using enterprise library data access block and created instance of dataacess for DataAccess function...
I think the most common way is to use it per request. Create it at the beginning, do what you need (most of the time these are operation that require common ObjectContext), dispose at the end. Most of DI frameworks support this scenario, but you can also use HttpModule to create context and place it in HttpContext.Current.Items. That is simple example:
public class MyEntitiesHttpModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += ApplicationBeginRequest;
application.EndRequest += ApplicationEndRequest;
}
private void ApplicationEndRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Items[#"MyEntities"] != null)
((MyEntities)HttpContext.Current.Items[#"MyEntities"]).Dispose();
}
private static void ApplicationBeginRequest(Object source, EventArgs e)
{
var context = new MyEntities();
HttpContext.Current.Items[#"MyEntities"] = context;
}
}
Definitely for every query. It's a lightweight object so there's not much cost incurred creating one each time you need it.
Besides, the longer you keep an ObjectContext alive, the more cached objects it will contain as you run queries against it. This may cause memory problems. Therefore, having the ObjectContext as a singleton is a particularly bad idea. As your application is being used you load more and more entities in the singleton ObjectContext until finally you have the entire database in memory (unless you detach entities when you no longer need them).
And then there's a maintainability issue. One day you try to track down a bug but can't figure out where the data was loaded that caused it.
Don't use a singleton.. everyone using your app will share that and all sorts of crazy things will happen when that object context is tracking entities.
I would add it as a private member
Like Luke says this question has been asked numerous times on SO.
For a web application, per request cycle seems to work best. Singleton is definitely a bad idea.
Per request works well because one web page has a User, maybe some Projects belonging to that user, maybe some Messages for that user. You want the same ObjectContext so you can go User.Messages to get them, maybe mark some messages as read, maybe add a Project and then either commit or abandon the whole object graph at the completion of the page cycle.
Late post here by 7 months. I am currently tackling this question in my app and I'm leaning towards the #LukLed solution by creating a singleton ObjectContext for the duration of my HttpRequest. For my architecture, I have several controls that go into building a page and these controls all have their own data concerns that pull read-only data from the EF layer. It seems wasteful for them to each create and use their own ObjectContext's. Besides, there are a few situations where one control may pull data into the Context that could be reused by other controls. For instance, in my masterpage, my header at the top of the page has user information that can be reused by the other controls on the page.
My only worry is that I may pull entities into the context that will affect the queries of other controls. I haven't seen that yet but don't know if I'm asking for trouble. I guess we'll see!
public class DBModel {
private const string _PREFIX = "ObjectContext";
// DBModel.GetInstance<EntityObject>();
public static ObjectContext GetInstance<T>() {
var key = CreateKey<T>();
HttpContext.Current.Items[key] = HttpContext.Current.Items[key] ?? Activator.CreateInstance<T>();
return HttpContext.Current.Items[key] as ObjectContext;
}
private static string CreateKey<T>() {
return string.Format("{0}_{1}", _PREFIX, typeof(T).Name);
}
}

Holding onto items after a postback

I have an ASP.NET web application and I want to be able to take items from a master list and store them temporarliy into one of four other lists. The 'other' lists need to survive post backs so that more items can be added to them. What direction would you suggest going with?
I have thought of using a generic list stored in memory, temporarliy storing the items into the database and calling them back on PostBack, or storing them into the viewstate, but I have a feeling that there is some solution that I'm missing that might be easier or better.
Josh laid out the states pretty well. My recommendation for a smaller list like he said would be using Session state. Using the DB would be a little messy because you have to maintain those temp tables and worry about multi-session access to the tables. Likewise, cache have the same problem. Viewstate gives you this with extra client traffic and insecure data. So if you're talking less than a few thousand instances on a low traffic server, then session is likely fine.
To make session easier to work with (and you can do this with caching and application state as well) is setup a container object that manages the lists.
//To use it in your page, you can easily access it via:
ListManagerContext.Current.MasterList.Add(4);
[Serializable]
public class ListManagerContext
{
public List<int> MasterList { get; set; }
public List<int> SubList1 { get; set; }
public List<int> SubList2 { get; set; }
public List<int> SubList3 { get; set; }
/// <summary>
/// Key used for the list manager context session variable.
/// </summary>
public const string ListManagerContextKey = "ListManagerContext";
/// <summary>
/// Gets the current ListManagerContext for this session.
/// If none exists, it returns a brand new one.
/// </summary>
[XmlIgnore]
public static ListManagerContext Current
{
get
{
HttpContext context = HttpContext.Current;
if (context != null && context.Session != null)
{
ListManagerContext data = null;
if (context.Session[ListManagerContextKey] == null)
{
data = new ListManagerContext();
context.Session[ListManagerContextKey] = data;
}
else
data = context.Session[ListManagerContextKey]
as ListManagerContext;
return data;
}
throw new ApplicationException("
No session available for list manager context.");
}
}
}
The first thing I would suggest is to see if you can remove the need of keeping state across postbacks.
If you can't do so (and ViewState is not applicable for some reason like bandwidth limitations or requiring data preservation even without a postback from a server form), I suggest consider using Session. You can configure session state to use a SQL Server database backend whenever you want without worrying about changing source code.
The database Idea is likely a poor one (assuming you're not dealing with large amounts of data).
Perhaps your best method would be to store the main list in ViewState, and have the other lists be lists of indexes to the first list.
The lists should automatically store the values they have in the viewstate. If they don't, you probably need to turn the viewstate on for these controls.
If you manually want to make the data survive the round trip, you can either store them in the session or in the viewstate yourself. Technically the viewstate makes the most sense, but if there's a lot of data, it can make the viewstate very large and take a long time to do a round trip. The only issue with the session is you'll have to make sure you clear it once you leave the page.
Don't use the database, that's not what its for.
You could store the list in ViewState or Session and assign it to a property. Here's simple example using a generic list of string, but can be any serializable type.
private List<String> MyTempList
{
get{return Session["mylist"] as List<String>;}
set{Session["mylist"] = value;}
}
protected void Page_Load(object source, EventArgs e)
{
if(!IsPostBack)
{
MyTempList = new List<String>();
}
else
{
MyTempList.Add("Something");
}
}
All of those are options and all have pro's and cons:
Database:
Storing items in the database is a fairly easy and consistent option. You do have to worry about making a round trip call to the database, but at least you have a centralized location to story the data that will scale easily with your web load. However, if this is short lived data, then you will have to worry about cleaning up your database as it might begin to get unwieldy.
Session/Cache:
Session affords a quick solution for in memory storage, but scaling can become problematic if the amount of data is very large. The more information you store in memory the less capacity you have for concurrent users. Also, if you start to add multiple web servers, then you will have to look into some sort of session state server to make sure users don't spontaneously lose their session.
Cache has basically all the same pros/cons except that there is the additional complexity of having to make sure you expire cache items, and manage concurrency issues.
Again, these are both easy to implement solutions, but don't scale as well under heavy load, or large amounts of data.
ViewState:
Viewstate is also an easy to implement solution and gets the load off the server and into the client, but can result in longer load times for the end user. Also it is important to remember that ViewState can be hacked, so if security is a concern then you want to take extra precautions to ensure data integrity.
Conclusion:
All in all, figure out what you want to accomplish and choose the solution that best fits your needs. Shove it behind some abstraction layer like an interface so you can easily change the details later, and then you won't have to worry as much. It's all about knowing what will work best in your particular scenario.

Resources