Search code examples
c#asp.netasp.net-web-apiin-memory-database

What is the best way to use in memory data in Asp.net Web API project for demo


I am building Asp.net Web API demo project, i don't want to use any data provider, neither entity framework nor Ado.net.

I build the Repository,

public class ProductRepo : IProductRepo
{
    private List<Product> products = new List<Product>();
    private int _nextId = 1;

    public ExternalProductDataRepo()
    {
        products.Add(new Product {Id=1, Name = "Toyata", Category = "Car", Price = 1.3M });
        products.Add(new Product {Id=2,  Name = "Ford", Category = "Car", Price = 3.75M });
        products.Add(new Product {Id=3, Name = "Hammer", Category = "Hardware", Price = 16.99M });
    }

    public IEnumerable<Product> GetAll()
    {
        return products;
    }

    public Product Get(int id)
    {
        return products.Find(p => p.Id == id);
    }

    public Product Add(Product item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        item.Id = _nextId++;
        products.Add(item);
        return item;
    }

    public void Remove(int id)
    {
        products.RemoveAll(p => p.Id == id);
    }

    public bool Update(Product item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        int index = products.FindIndex(p => p.Id == item.Id);
        if (index == -1)
        {
            return false;
        }
        products.RemoveAt(index);
        products.Add(item);
        return true;
    }
}

But, in every app hit, a new instance of ProductRepo class is created, so even though i save the data, it never persisted.

Also, i have the option of using, System.Web.Cache, to hold the products list in Cache, but it is for a different purpose and for a limited period of time, also it makes isolated unit testing difficult. So, what is the suggestion to build the successive demo project with products CRUD operation?


Solution

  • You want your repository to be a singleton. There are multiple ways to achieve this, but if this demo code is going to become operational in some way, I would suggest integrating a dependency injection provider into your code. For example, you could use unity.

    • You set up your repository as a singleton in the container.
    • You controllers will get passed the IProductRepo interface. This means that if you decide to change the implementation to an actual data provider, your code will not need to change - you will simply change the registration in your DI container.

    Here are some resources to help you get started if you want to implement this path:

    1. Install Unity.WebAPI nuget package. See http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package
    2. In your App_Start folder, add a static UnityConfig class:

      public static class UnityConfig
      {
          public static void RegisterComponents()
          {
              var container = new UnityContainer();
      
              container.RegisterType<<IProductRepo>,<ProductRepo>> (new ContainerControlledLifetimeManager());
              container.Resolve<IProductRepo>();
      
              GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
          }
      }
      
    3. In your Global.asax file, add the following line: UnityConfig.RegisterComponents();

    4. Now in the constructor of your controller, just pass a member of type IProductRepo. This will be initialized for you by Unity, and will be the same instance every app hit since it is created once by Unity.