My simple repository's getAll method:
public List<ListModel> GetAllLists()
{
using (MySqlConnection connection = new MySqlConnection(this.connectionString))
{
return connection.Query<ListModel>("SELECT * FROM projectx.lists").AsList();
}
}
I'm using this class I've found here in so to handle caching:
public class CacheUtils : ICacheService
{
public TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback, double durationInMinutes = 120) where TValue : class
{
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
Debug.WriteLine("Not cached");
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
else
Debug.WriteLine("Cached!");
return item;
}
public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback, double durationInMinutes = 120) where TValue : class
{
string cacheKey = string.Format(cacheKeyFormat, id);
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback(id);
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
}
Home controller:
public ActionResult Index()
{
ListRepository listRep = new ListRepository();
CacheUtils cache = new CacheUtils();
return View(cache.Get("lists", listRep.GetAllLists));
}
Question, is there a better way of handling cache than calling the helper from the controller? Ideally, it should be inside the repository method. But do I need to repeat the check for existing cache data on every single method of the repository? Ie.:
public List<ListModel> GetAllLists()
{
var lists = Cache["lists"];
if(lists == null)
{
using (MySqlConnection connection = new MySqlConnection(this.connectionString))
{
lists = connection.Query<ListModel>("SELECT * FROM projectx.lists").AsList();
}
Cache["lists"] = lists;
}
return ((List<ListModel>)lists);
}
Use a decorator pattern and don't polute business or ui with caching logic.
Wire it up with something like ninject (or poor bastards if you dont want to add a DI) I'd recommend marking it as single instance.
Benefits include:
Adding a invalidating method like void Save(ListModel) is easy to
invalidate the cache.
Your top layer and bottom layer know nothing
about the fact they have been cached.
You can also decorate again to add in logging, profiling, etc
You can also control the caching life cycle
you don't polute the controller level with caching logic
easy to remove
So something like the below would work. For how too add decorators in ninject see https://stackoverflow.com/a/8910599/1073280
public class MyHomeController
{
private readonly IListCrud _listcrud;
public MyHomeController(IListCrud listcrud)
{
_listcrud = listcrud;
}
public ActionResult Index()
{
return View(_listcrud.GetAllLists());
}
}
public interface IListCrud
{
List<ListModel> GetAllLists();
}
public class ListCrud : IListCrud
{
public List<ListModel> GetAllLists()
{
using (MySqlConnection connection = new MySqlConnection(this.connectionString))
{
return connection.Query<ListModel>("SELECT * FROM projectx.lists").AsList();
}
}
}
public class ListCrudCache : IListCrud
{
private readonly ICacheService _cache;
private readonly IListCrud _inner;
public ListCrudCache(ICacheService cache, IListCrud inner)
{
_cache = cache;
_inner = inner;
}
public List<ListModel> GetAllLists()
{
return _cache.Get("lists", _inner.GetAllLists);
}
}
Opinion: maybe just to keep the code small but be careful using select * with a ORM. if someone renames or removes a column you wont have any easy to unit test/detect failure mechanism.
In my opinion it shouldn't be in the repository, as it (to me) smells like violation or SRP. Caching should be a higher level service above the repository.
You need to think about what actually needs the benefits of the caching. If the caching is for speeding up the WEB API interface, then having it in the controller is the best way by far. If you need caching elsewhere too, consider introducing some middle layer service classes and put caching there, but I would always make it optional in some way.
Related
Im using asp.net core. Here is the basic way to use model with controller.
public class BookController : Controller
{
private readonly ApplicationDbContext _context { get; set; }
public BookController(ApplicationDbContext context)
{
_context = context;
}
public IActionResult Create(Book model)
{
// adding new model
}
public IActionResult Edit(Book model)
{
// modifying the model
}
public IActionResult Delete(Book model)
{
// removing the model
}
}
My question: when shall/should I implement the code inside the controller? When shall/should I implement it in another class?
Something like this:
public interface IBook
{
int Add(Book book);
int Update(Book book);
int Remove(Book book);
}
public class BookData : IBook
{
private readonly ApplicationDbContext _context { get; set; }
BookData(ApplicationDbContext context)
{
_context = context
}
public int Add(Book model)
{
// ...
return _context.SaveChanges();
}
// other implements...
}
Then, calling it inside controller:
public IActionResult Create(Book model)
{
var bookData = new BookData(_context);
int result = bookData.Add(model);
// ...
}
For the interface, I think it may be useful for the case: I have many controllers that require same action/method names.
Example: MessageController requires 3 actions/methods at least (Create/Add, Edit/Update, Delete/Remove). It's same to NotificationController class, CommentController class...
So, the interface can be improved to:
public interface IMyService<T> where T : class
{
int Add(T model);
int Update(T model);
int Remove(T model);
}
public class MyService<T> : IMyService<T> where T : class
{
private readonly ApplicationDbContext _context { get; set; }
public MyService(ApplicationDbContext context)
{
_context = context;
}
public int Add(T model)
{
Type type = typeof(model);
if (type == typeof(Book))
{
// adding new book model
}
else if (type == typeof(Comment))
{
// adding new comment model
}
// ...
return -1;
}
// other implements...
}
Do I misunderstand something?
If I read it correctly with data classes you actually means repository (which is an abstraction over the persistence layer). You should always encapsulate persistence logic behind a class (be it via repository pattern, command/query pattern or request handler) and use it instead of directly using the context in your service classes.
That being said, you can directly inject your BookData to your controller instead of the ApplicationDbContext. One thing you should consider you lose in your current implementation is the Unit of Work pattern. Right now, every add will instantly persist the data.
This may not be what you want, so you should move the _context.SaveChanges(); outside of the Add/Remove/Update methods and call it explicitly. This allows you to insert i.e. 10 records and if one of them fails, nothing will be persisted to the database.
But if you call _context.SaveChanges(); after each insert and you get an error in the 8th (of 10) records, then 7 get persisted and 3 will be missing and you get inconsistent data.
Controller shouldn't contain any logic at all, only do short validation of the input model (ModelState.IsValid check) and if its okay, call the services which do all the logic and report the result back to the user. Only in very simple tutorials and guides logic is put into the controller action for reasons of simplicity. In real world applications you should never do that. Controllers are much harder to unit test than service classes.
I want to change my session proviced to statically typed - I just hate typing strings because of many many errors I do.
What technology am I using? ASP.NET MVC via EXT.NET MVC
I was trying to do that using web.config but the problem is that after add session state to it visual is not going to compile my code because of that session should be using strings as keys.
I want to use session by enums such as :
public enum SessionEnum{Model}
public class Bar{
void foo(){
Session[SessionEnum.Model] = "blah";
}
}
I am aware that I can create wrapper converting enums to strings but it's not very satisfying solution for me.
public class StorageWrapper{
public object this[SessionEnum enum]{ get{return Session[enum.toString()]}; //+set
}
What I did was create static object for base class for all of my controllers and then I was able to use it across them but after closing and opening the page again I wasn't able to get values from it. I guess I should serialize them somehow but I have no idea how.
Is there any way to do that?
EDIT
My session now looks like this :
[Serializable]
public abstract class DataWrapper<T> : HttpSessionStateBase
{
Dictionary<T, object> Dictionary { get; set; } = new Dictionary<T, object>();
public object this[T a]
{
get
{
try
{
return Dictionary[a];
}
catch
{
return null;
}
}
set { Dictionary[a] = value; }
}
}
[Serializable]
public class SessionWrapper : DataWrapper<SessionNames>
{}
public enum SessionNames { Model, Login, LastOpenedFile }
It's very simple.
Create a UserSession object which does everything you want (holds your values as enum etc), instantiate it, then put it in the session.
var US = new UserSession();
US.stuff = somestuff;
Session["UserSess"] = US
Then you can just always use Session["UserSess"].stuff;
Mmmm, wouldn't you use static const string instead of an enum?
using System.Web;
public static class SessionEnum
{
public static const string Model = "_Session_Model";
public static const string Login = "_Session_Login";
public static const string LastOpenedFile = "_Session_LastOpenedFile ";
}
class test
{
void test()
{
Session[SessionEnum.Model] = "blah";
}
}
I am stuck with this and I wonder what is the best way to approach this problem. I have a WebApi controller where I want to inject ICommand instance but I can know what is the instance I need once I inspect the Post request data. I'll give an example to be more clear but my question also applies to Winform events where you receive an event argument and depending of this event arg you want to have different implementation injected.
public class TestController : ApiController
{
public object Post(int id)
{
ICommand command = null;
if(id = 1)
{
command = new Id1Command();
}
else
{
command = new Id2Command();
}
return new object();
}
}
The only thing I can think of is creating a factory that accepts unity container as argument and inside that factory to call container.Resolve with named instance.
My problem with that is that I am taught that you shouldn't register or resolve outside your composition root and that is violation of the good practices (according Mark Seemann). I am looking for the best design for this problem in general.
I would use a CommandFactory and pass it to the TestController:
public class TestController : ApiController
{
private readonly ICommandFactory mCommandFactory;
public TestController(ICommandFactory CommandFactory)
{
mCommandFactory = CommandFactory;
}
public object Post(int id)
{
ICommand command = null;
if(id = 1)
{
command = CommandFactory.CreateId1Command();
}
else
{
command = CommandFactory.CreateId2Command();
}
return new object();
}
}
Now you have to make sure that Unity is creating the TestController. To do so, you have to implement, configure and set an IDependencyResolver. Check Dependency Injection in ASP.NET Web API 2.
Edit to your comment:
For this scenario you can use an autofactory using a functor that takes an int:
public class TestController : ApiController
{
private readonly Func<int, ICommand> mCommandFactory
public TestController(Func<int, ICommand> CommandFactory)
{
mCommandFactory = CommandFactory;
}
public object Post(int id)
{
var command mCommandFactory(id);
return new object();
}
}
The registration should look like this:
container.RegisterType<Func<int, ICommand>>(new InjectionFactory(
c => new Func<int, ICommand>(
id =>
{
if (id == 1)
{
return new Command();
}
else
{
return new Command2();
}
})));
Note: You still have to set the DependencyResolver!
Rather simple question regarding entity framework and how to consume the objectcontext.
In a asp.net webform application I am implementing most of data getters in a data class and trying to determine if its better (in a generic sense of better) to have a private context for the entire class or declare a context in each of the methods.
Example 1:
public class Data
{
private MyEntity context = new MyEntity();
public Customer GetCustomer()
{
return context.Customer.Single();
}
public Order GetOrder()
{
return context.Order.Single();
}
}
Or Example 2:
public class Data
{
public Customer GetCustomer()
{
using (MyEntity ctx = new MyEntity())
{
return context.Customer.Single();
}
}
public Order GetOrder()
{
using (MyEntity ctx = new MyEntity())
{
return context.Order.Single();
}
}
}
Personally im a big fan of using a shared context across your whole post back, however neither of these scenarios really achieve this. My personal preference is to use a dependency injection container such as ninject to manage the lifecycle of your EF context. This means that you can make your whole postback transactional.
in terms of implementation I would go for soemthing like the following:
public class Data
{
private MyContext _context;
public Data(MyContext context)
{
_context = context;
}
public Customer GetCustomer()
{
return _context.Customer.Single();
}
public Order GetOrder()
{
return _context.Order.Single();
}
}
with a binding similar to:
Bind<MyContext>().ToSelf().InRequestScope();
In an effort to make my entities persistent ignorant and make my repositories testable, I've implemented a repository pattern like so:
public interface IJobRepository : IRepository<Job>
{
Job GetJobById(int jobId); //Special case where I'm eager loading other entities
void SaveJob(Job job, Job originalJob);
}
public class JobRepository : IJobRepository
{
private readonly IContext _context;
public JobRepository()
{
_context = new CustomObjectContext();
}
public JobRepository(UnitOfWork unitOfWork)
{
_context = unitOfWork.Context;
}
//Basic GetAll, GetById, Add and Delete methods from IRepository<T> Interface here
//omitted for brevity
public Job GetJobById(int jobId)
{
var job = _context.Jobs.Include("Company").Include("Location").
Include("PlantInfo").Where(j => j.Jobid == jobId).SingleOrDefault();
_context.DisposeContext();
return job;
}
public void SaveJob(Job job, Job originalJob)
{
if (job.Jobid > 0)
{
// Update
_context.Jobs.Attach(originalJob);
_context.PlantInfoes.Attach(originalJob.PlantInfo);
_context.Jobs.ApplyCurrentValues(job);
_context.PlantInfoes.ApplyCurrentValues(job.PlantInfo);
Note: ApplyCurrentValues is an extension method I'm using on the ObjectSet
}
else
{
// Create
_context.Jobs.AddObject(job);
}
_context.Save();
}
}
public class UnitOfWork
{
private readonly IContext _context;
public UnitOfWork()
{
_context = new CustomObjectContext();
}
public UnitOfWork(IContext context)
{
_context = context;
}
public string Save()
{
return _context.Save();
}
internal IContext Context
{
get { return _context; }
}
}
public interface IContext
{
IObjectSet<Job> Jobs { get; }
IObjectSet<Company> Companies { get; }
IObjectSet<Location> Locations { get; }
IObjectSet<PlantInfo> PlantInfoes { get; }
string Save();
}
My ObjectContext inherits from IContext...So my understanding is that I will only use the overloaded constructor on the repository to facilitate unit tests or to use it in the case that I want to use the same context (not desirable based on this post I found on SO "Entity Framework and Connection Pooling" -- Is this right?
Also, assuming the context only gets disposed when the repository is garbage collected, I have to dispose the context explicitly to avoid the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." exception when attaching the entity prior to a save.
That said, what is the best practice for managing the DataContext in a manner that keeps your entities persistent ignorant and repositories testable?
Note: This is an asp.net webapplication; UnitOfWork and IContext implementation was based on examples from "Programming Entity Framework", Second Edition by Julia Lerman Ch24.
Thanks in advance!
Firstly, I would ensure that whatever my "consumable" object is (either repository or unit of work, depending on your setup) implements IDisposable. When your consumbed object is disposed of, then you would dispose your underlying context.
For instance, if you're using your UnitOfWork as the consumable object (the one that gets created and called in your application), it would look something like:
public class UnitOfWork : IDisposable
{
// All the other stuff you had before plus:
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
}
(Note: This can also be done on your repositories if they're the ones being consumed directly)
And then, you have a few options in your application. If you are going to use the UnitOfWork directly, you can use it like:
public void SomeMethodThatAccessesYourData ()
{
using (var unitOfWork = new UnitOfWork (/*Load in the context*/))
{
// Access your data here.
}
}
Or, in your Web Forms or MVC object you can use constructor injection and dispose of it when the Web Forms or MVC object is disposed of:
// If you're using MVC:
public class MyController : Controller
{
private UnitOfWork _unitOfWork;
public MyController (UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public override Dispose (bool Disposing)
{
if (Disposing && _unitOfWork != null)
{
_unitOfWork.Dispose ();
}
}
}
The same idea stands for a web forms Page.
The main reason for using the constructor overload is for Inversion of Control (IOC). It helps with both unit testing and with production code when used with an IoC Container. WebForms doesn't lend itself well to IoC, but it is really easy with MVC.
Edit
I don't really see the connection with your repositories and the unit of work. Usually you access the repositories from a unit of work or, in other implementations, you request a unit of work from your target repository. In your implementation (which I understand is not your own) there seems to be no need for both.
Edit 2
If the UoW is overkill for your application, and you know you can use IoC to inject your IContext, and you don't have very many repositories, you can do something like:
public IRepository<T> : IDisposable { }
public IJobRepository : IRepository<Job> { /* All the stuff you put here */ }
public JobRepository : IJobRepository
{
private IContext _context;
...
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
public JobRepository (IContext context)
{
_context = context;
}
}
Then, how you use it depends on your specific task. I'm not a fan of this direct use of IRepository, but this answer is getting too long.