Should repositories be implemented as singletons as best practice? - c#

I have a small webapp that uses EntityFramework to store stuff via repositories into the database.
What I've done so far (based on all the tutorials I read) is create a repository where I need it, as shown below:
In CustomMembershipProvider:
public CustomMembershipProvider()
{
_userRepository = new UserRepository(new TenantApplicationContext());
}
In my RegisterController:
public TenantRepository TenantRepository { get; set; }
public UserRepository UserRepository { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
if (TenantRepository == null) { TenantRepository = new TenantRepository(TenantApplicationContext); }
if (UserRepository == null) { UserRepository = new UserRepository(TenantApplicationContext); }
base.Initialize(requestContext);
}
The point is, that I instantiate the UserRepository twice. This becomes a problem when I create a User in one instance, and try to retrieve it in the other instance, and I did not call SaveChanges in between.
The problem lies here:
// Snippet from the register controller class
if (!UserRepository.Exists(model.AccountableEmailAddress))
{
// 1 - Create the user via a custom MembershipProvider
// Note, the CustomMembershipProvider has it's own instance of UserRepository
var createStatus = MembershipService.CreateUser(
model.AccountableUser,
model.Password,
model.AccountableEmailAddress);
if (createStatus == MembershipCreateStatus.Success)
{
// Left out irrelevant code
AdministerUserAndTenant(tenant.Name, model.AccountableEmailAddress);
}
}
private void AdministerUserAndTenant(string tenantName, string emailAddress)
{
// 2 - Try to retrieve the user from a different (!) instance of UserRepository
var user = UserRepository.GetUser(emailAddress);
var tenant = TenantRepository.GetTenantByName(tenantName);
tenant.Users.Add(user);
TenantApplicationContext.SaveChanges();
}
I hope you can still follow, tried to leave out unnecessary parts.
What is the best way to deal with issues like this?
PS: I'm not very fond of the Singleton pattern, so if possible don't go there :).

When exactly does it become a problem? Cause that's where the answer lies. Classes that should know of each other's unsaved changes should use the same repository instance. Since they are probably related, you'll manage passing a reference between them.
If there's reason why all of your application should have one single repository, use Dependency Injection.

Related

Saving data to multiple tables with dependency injection and maintaining transection in asp.net core app

I have simple classes to saves and get data (not like repository pattern). But while saving data to multiple tables I want to maintain a transaction. So I just went through Unit of work pattern, but that will require me to do a lot of changes. So I'm thinking if my approach will do the same as UOF.
Here's my code:
CalalogueRepository:
public interface ICalalogueRepository
{
void Create(string guid, string fileName);
}
public class CalalogueRepository : ICalalogueRepository
{
private CatalogueContext _catalogueContext;
public CalalogueRepository(CatalogueContext catalogueContext)
{
_catalogueContext = catalogueContext;
}
public void Create(string guid, string fileName)
{
_catalogueContext.Catalogues.Add(new Catalogue
{
CatalogueId = guid,
FileName = fileName
});
}
}
StuffRepo:
public interface IStuffRepo
{
void Create(string guid, List<StuffModel> myStuff);
}
public class StuffRepo : IStuffRepo
{
private CatalogueContext _catalogueContext;
public StuffRepo(CatalogueContext catalogueContext)
{
_catalogueContext = catalogueContext;
}
public void Create(string guid, List<StuffModel> myStuff)
{
//add stuff to _catalogueContext.StuffTable.Add
}
}
Finally a class that does the SaveChanges and Commit:
public class UOW : IUOW
{
private CatalogueContext _catalogueContext;
private ICalalogueRepository _calalogueRepo;
private IStuffRepo _stuffRepo;
public UOW(CatalogueContext catalogueContext,
ICalalogueRepository calalogueRepo,
IStuffRepo stuffRepo)
{
_catalogueContext = catalogueContext;
_calalogueRepo = calalogueRepo;
_stuffRepo = stuffRepo;
}
public void Save (string guid, string fileName, List<StuffModel> myStuff)
{
using (IDbContextTransaction transection = _catalogueContext.Database.BeginTransaction())
{
_calalogueRepo.Create(guid, fileName);
_stuffRepo.Create (guid, myStuff);
_catalogueContext.SaveChanges();
transection.Commit();
}
}
}
I think there is only 1 CatalogueContext throughout the call.
Ok, so as you can see here, AddDbContext is the right way to register it as you wrote in the comment on the question.
Here it says that AddDbContext will register the context as scoped.
And here you can find what scoped means.
Overall I think you are right that your code will use the same context throughout the Save method.
Couple thoughts:
Probably you want to have a try-catch in case an exception is thrown and you want to rollback
If you are not sure if it's working why not try it? You should test your code/application anyways.
Probably this could be done in a better way, but I don't have the context about the rest of your code/application, so I cannot tell. (Not sure what you mean by "...Unit of work pattern, but that will require me to do a lot of changes." for example.)
Now the Create methods not self-contained, meaning if you just want to add a new item to the table it is not enough to call Create, but separately call SaveChanges(). This is not an explicit problem, but has to be kept in mind and might be a little bit confusing for new developers on the project.

Validation in Business Layer: How to call service methods?

I have created a struct on validating models on Business Layer which is based on Steven's answer.
It is working well but something confuses my mind. I inject UserService in CreateUserValidator to able to use GetUser method. This means I call validator in UserService and create a new UserService instance to check whether user exist.
UserService -> [ValidateUser -> new UserService().GetUser()]
It works but seems to be a very bad design. But I have to use that method.
Could you please let me know how I can solve this problem, or Shouldn't I worry about it?
public class CreateUser
{
public string Name { get; set; }
public string Email { get; set; }
}
public sealed class CreateUserValidator : Validator<CreateUser>
{
private IUserService _userService;
public CreateUserValidator(IUserService userService)
{
_userService = userService;
}
protected override IEnumerable<ValidationResult> Validate(
CreateUser entity)
{
var user = _userService.GetUserByEmail(entity.Email);
if (user != null)
{
yield return new ValidationResult("Email", "Email address is already exist!");
}
}
}
UserService.cs
public partial class UserService : IUserService
{
IGenericUnitofWork _uow = null;
private readonly IValidationProvider _validationProvider;
public UserService(IGenericUnitofWork uow, IValidationProvider validationProvider)
{
_uow = uow;
_validationProvider = validationProvider;
}
public User CreateUser(CreateUser createUser)
{
this._validationProvider.Validate(createUser);
var user = new User()
{
Email = createUser.Email,
Name = createUser.Name,
};
_uow.Repository<User>().Insert(User);
_uow.SaveChanges();
return user;
}
public User GetUser(string email)
{
var user = _uow.Repository<User>().Where(m => m.Email == email).FirstOrDefault();
return user;
}
}
You dependency graph is cyclic. As described in section 6.3 of Dependency Injection in .NET second edition, dependency cycles are often caused by Single Responsibility Principle violations, as is the case in your design.
The problem is that UserService has too many responsibilities: Creating a user is a different responsibility than getting a user. Creating a user can become a very complex use case, as the validation logic hints at, while getting a user is something typically quite simple. It would therefore be beneficial to split UserService into multiple smaller classes. This would allow the validator to depend on the service that allows retrieving the user by its mail address, while the 'create user' service can depend on the validator.
To take it even one step further, you might want to remove validation from the 'create user' service completely. Validation is a cross-cutting concern, and mixing it with the class that contains the business logic, makes such class harder to maintain.
A design that might benefit you is one where you place all state changing business actions behind a common abstraction, as described here.

Moving logic from controller action to a "service layer" without using IoC/DI, UoW and repository patterns in ASP.NET MVC

Recently i've working on an ASP.NET MVC5 project, i dived right in and wrote all my logic right in the action method and after doing this for a few controllers i've noticed that i have been duplicating certain business rules and could do with being lifted out and shared between controllers.
From what i've read, the m in asp.net mvc is a layer consisting of entities, viewmodels and services, the latter holding all your shared business logic
now i'm trying to keep things as simple as possible, i don't want to wrap entity framework in some UoW/Repo and use it as-is, it is very unlikely that i'll stop using entity framework in this applications lifetime and i'm not doing unit tests and i'm not that bothered about tight coupling, so i don't feel i need an IoC container, but all the tutorials i've read seems to use either an IoC container or wraps dbcontext/ef in a UoW/Repo.
I've read that there should only be a single instance (which in the tutorials i've seen is managed via an IoC container) of DbContext per httprequest, would this be achieved by instantiating it in the controllers constructor and then passing that reference to any services needed in the controller and then disposing it at the end of the request? is this the correct way of managing dbcontext?
Controller example:
public class SupplierController : Controller
{
private Meerkat3Context context;
private SupplierService supplierService;
private ratingService SupplierRatingService;
public SupplierController()
{
// instantiate the dbcontext
this.context = new Meerkat3Context();
// pass dbcontext into the constructors of my services
this.supplierService = New SupplierService(context);
this.ratingService = New SupplierRatingService(context);
}
public ActionResult Index(Guid id)
{
var supplier = supplierService.getSupplier(id);
// construct viewmodel
return new SupplierIndexViewModel()
{
SupplierId = supplier.Id,
SupplierName = supplier.Name,
SupplierRating = ratingService.getHighestRating(supplier.Id),
NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id),
// etc
};
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
context.Dispose();
}
base.Dispose(disposing);
}
}
Service examples:
public class SupplierService
{
private Meerkat3Context context;
public SupplierService(Meerkat3Context context)
{
this.context = context;
}
public Supplier getSupplier(Guid id)
{
return context.Where(x => x.SupplierId == id)
.FirstOrDefault()
.Select(x => new Supplier()
{
Id = x.Id,
Name = x.Name
// etc
});
}
public Supplier getNearbySuppliers(Guid id)
{
return context.Suppliers.Where(x => context.SupplierAddresses
.Where(y => y.AddressTypeId == AddressTypes.Location)
.Select(z => z.Address.TownCity)
.Contains(x.SupplierAddresses
.Where(y => y.AddressTypeId == AddressTypes.Location)
.FirstOrDefault()
.Address.TownCity)
);
}
}
public class SupplierRatingService
{
private Meerkat3Context context;
public RatingService(Meerkat3Context context)
{
this.context = context;
}
public SupplierRating getHighestRating(Guid id)
{
return context.SupplierRating
.Where(x => x.SupplierId == id)
.OrderBy(x => x.RatingValue)
.FirstOrDefault()
}
}
If you're trying to strip out the repeated code, this should be fairly simple. In VS you can highlight a section of code and use the hotkeys Ctrl+R,Ctrl+M for refactor, or you can do so by using the context menu highlight code section > right-click > Refactor > Extract Method.
If the usage of the repeated code can be replicated for all entities, you can create a static class that houses this common functionality.
public sealed class Utlities
{
public static CommonA() { }
public static CommonB() { }
... etc...
}
And you can call them easily using Utilities.CommonA(). Another way to reduce redundancy is to use ViewModels. Basically create a copy of the entity you want to use as a ViewModel with additional properties required for the View. If the models have data in common, create a base class to inherit those commonalities from.
public class BaseViewModel
{
public Type Prop {get; set;}
public Type Prop2 {get; set;}
...etc...
}
public class SpecificViewModel : BaseViewModel
{
SpecificViewModel(Type Prop, Type Prop2) : base(Prop, Prop2, ...etc...) { }
public Type specificProp {get; set;}
...etc...
}
If I understood your question correctly that is.
If what you want is simply moving out reusable logic then your approach is good enough. But please bear in mind that:
it isn't testable (you can't isolate your dependencies and
You're still duplicating the logic, even if it's simply an object construction logic (e.g., in every controller where you need SupplierService you'll have to instantiate Meerkat3Context as well). That can get quite tedious (and that's where DI comes in handy)
With an IoC container your controller would look like.
public class SupplierController : Controller
{
//the controller doesn't need to create the db context now
//this concern is handled now by the IoC container
private SupplierService supplierService;
private RatingService SupplierRatingService;
public SupplierController(SupplierService supplierService, RatingService ratingService)
{
// we don't have to pass the db context now to services, since we retrieve the services from the IoC container. The IoC container auto-wires the services
this.supplierService = supplierService;
this.ratingService = ratingService;
}
public ActionResult Index(Guid id)
{
var supplier = supplierService.getSupplier(id);
// construct viewmodel
return new SupplierIndexViewModel()
{
SupplierId = supplier.Id,
SupplierName = supplier.Name,
SupplierRating = ratingService.getHighestRating(supplier.Id),
NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id),
// etc
};
}
// the controller doesn't need a dispose method since the IoC container will dispose the dbcontext for us
}
You don't have to follow the Dependency Inversion Principle to use an IoC container, but you can count on a IoC container to create and to manage the lifetime of your services objects.
You configure the IoC container to create a single instance of a dbcontext per a web request. The good part is this is configurable and, if you later decide is better to have a different dbcontext instance per service, then you just change this in a single place and not in every controller and every action method where you use the new keyword.

C# MVVM Handling and Passing UserID to different Models and ViewModels

My current implementation of passing UserID in my application is through the constructor.
i.e. SomeObject s = new SomeObject(userID)
Where in there is a code behind that does things based on the userID. The userID is further keep tracked by adding another property named "CurrentUser", however this seems to be a dirty solution as I have to implement it to all ViewModels and it seems to violate the "DRY" concept.
The second approach I have in mind is creating a public static variable on my MainWindowViewModel where all my other models can refer to it as MainWindowViewModel.CurrentUser.
Is one of the two approach the correct way to do this or is there a better approach that i don't know about?
You need to carefully analyze up front what you want to achieve with your application. Are you happy with there only ever being one selected client? Or will you need to have multiple clients being viewed or edited at a time (i.e. you have an MDI style app)?
Going with the single client approach is easy, you can implement the global property bag as already mentioned in other answers. But I will advise caution: if you build your app on the assumption there will only ever be one selected client it becomes a real PITA to try to refactor to make it multi-client capable. Using a centralized property bag or "session service" like this is indeed decoupling state from the VM, but the centralized service can still turn into a monstrosity over time and you build up too much dependence on it.
If you do want to go the multi-client route, then you are on the right track - but instead of passing a client identifier in on the constructor, pass (inject) the entire client data object. The chances are that you already have most of the client details available from the piece of UI that invokes the client oriented VM, so pass it in and save having to make another trip to your database to get the details.
Don't tie a current user to a ViewModel. I typically opt for a SessionService of some kind. If you're using Dependency Injection (DI), register a singleton of an ISessionService and concrete implementation. If your not using DI, then just have your app start create a singleton, like a SessionService.Current. Then you can put any items you need in here. Then each ViewModel can ask for the SessionService.Current.User and they have it. Your ViewModels shouldn't know about each other, but they can know about services. This keeps it DRY and loosely coupled, especially if you only access these session variables using the interface of an ISessionService and not the concrete implementation. This allows you to mock one up very easily without changing any ViewModel code.
What you have here is the problem of Communication between ViewModels. There are a number of solutions but my fave is the Mediator Pattern:
using System;
namespace UnitTestProject2
{
public class GetDataViewModel
{
IMediator mediator;
public GetDataViewModel(IMediator mediator)
{
this.mediator = mediator;
this.mediator.ListenFor("LoggedIn", LoggedIn);
}
protected string UserId;
protected void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
IMediator mediator;
public LoginViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
this.mediator.RaiseEvent("LoggedIn", this.UserId);
}
}
public interface IMediator
{
public void ListenFor(string eventName, EventHandler action );
public void RaiseEvent(string eventName, object data);
}
}
I Haven't implemented the Mediator here, because it can get quite involved and there are a number of packages available. but you can see the idea from my simple interface. Essentially the Mediator provides a Global list of EventHandlers which any Viewmodel can call or add to. You still have the problem of where to store the event names. Its nice to have these in enums, but that gives you a coupling problem. (a problem I usually ignore)
Alternatively you can have a Controller or (MasterViewModel if you love MVVM)
using System;
namespace UnitTestProject3
{
public class GetDataViewModel
{
protected string UserId;
public void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
public EventHandler OnLogin;
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
if (this.OnLogin != null)
{
this.OnLogin(this.UserId, null);
}
}
}
public class Controller // or MasterViewModel
{
public void SetUp()
{
GetDataViewModel vm1 = new GetDataViewModel();
LoginViewModel vm2 = new LoginViewModel();
vm2.OnLogin += vm1.LoggedIn;
//wire up to views and display
}
}
}

Entity Framework Best Practices In Business Logic?

I am using the Entity framework for the first time, and would like to know if I am using in the best practice.
I have created a separate class in my business logic which will handle the entity context. the problem I have, is in all the videos I have seen they usually wrap the context in a using statement to make sure its closed, but obviously I can't do this in my business logic as the context will be closed before I can actually use it?
So is this ok what I'm doing? A couple of examples:
public IEnumerable<Article> GetLatestArticles(bool Authorised)
{
var ctx = new ArticleNetEntities();
return ctx.Articles.Where(x => x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
}
public IEnumerable<Article> GetArticlesByMember(int MemberId, bool Authorised)
{
var ctx = new ArticleNetEntities();
return ctx.Articles.Where(x => x.MemberID == MemberId && x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
}
I just want to make sure I'm not building something that's going to die when a lot of people use it?
It really depends on how to want to expose your repository/data store.
Not sure what you mean by "the context will be closed, therefore i cannot do business logic". Do your business logic inside the using statement. Or if your business logic is in a different class, then let's continue. :)
Some people return concrete collections from their Repository, in which case you can wrap the context in the using statement:
public class ArticleRepository
{
public List<Article> GetArticles()
{
List<Article> articles = null;
using (var db = new ArticleNetEntities())
{
articles = db.Articles.Where(something).Take(some).ToList();
}
}
}
Advantage of that is satisfying the good practice with connections - open as late as you can, and close as early as you can.
You can encapsulate all your business logic inside the using statement.
The disadvantages - your Repository becomes aware of business-logic, which i personally do not like, and you end up with a different method for each particular scenario.
The second option - new up a context as part of the Repository, and make it implement IDisposable.
public class ArticleRepository : IDisposable
{
ArticleNetEntities db;
public ArticleRepository()
{
db = new ArticleNetEntities();
}
public List<Article> GetArticles()
{
List<Article> articles = null;
db.Articles.Where(something).Take(some).ToList();
}
public void Dispose()
{
db.Dispose();
}
}
And then:
using (var repository = new ArticleRepository())
{
var articles = repository.GetArticles();
}
Or the third-option (my favourite), use dependency injection. Decouple all the context-work from your Repository, and let the DI container handle disposal of resources:
public class ArticleRepository
{
private IObjectContext _ctx;
public ArticleRepository(IObjectContext ctx)
{
_ctx = ctx;
}
public IQueryable<Article> Find()
{
return _ctx.Articles;
}
}
Your chosen DI container will inject the concrete ObjectContext into the instantiation of the Repository, with a configured lifetime (Singleton, HttpContext, ThreadLocal, etc), and dispose of it based on that configuration.
I have it setup so each HTTP Request gets given a new Context. When the Request is finished, my DI container will automatically dispose of the context.
I also use the Unit of Work pattern here to allow multiple Repositories to work with one Object Context.
You may have also noticed I prefer to return IQueryable from my Repository (as opposed to a concrete List). Much more powerful (yet risky, if you don't understand the implications). My service layer performs the business logic on the IQueryable and then returns the concrete collection to the UI.
That is my far the most powerful option, as it allows a simple as heck Repository, the Unit Of Work manages the context, the Service Layer manages the Business Logic, and the DI container handles the lifetime/disposal of resources/objects.
Let me know if you want more info on that - as there is quite a lot to it, even more than this surprisingly long answer. :)
I would have the ctx as a private variable within each class, then create a new instance of this each time and then dispose when finished.
public class ArticleService
{
private ArticleEntities _ctx;
public ArticleService()
{
_ctx = new ArticleEntities();
}
public IEnumerable<Article> GetLatestArticles(bool Authorised)
{
return _ctx.Articles.Where(x => x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
}
public IEnumerable<Article> GetArticlesByMember(int MemberId, bool Authorised)
{
return _ctx.Articles.Where(x => x.MemberID == MemberId && x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
}
public void Dispose()
{
_ctx.Dispose();
_ctx = null;
}
}
Then when calling this.
ArticleService articleService = new ArticleService();
IEnumerable<Article> article = articleService.GetLatestArticles(true);
articleService.Dispose(); // killing the connection
This way you can also add/update other objects within the same context and call a save method which saves any changes to the db through the Entity.
In my experience this code is not good, because you lose the capacity to navigate relationships through navigation properties.
public List<Articles> getArticles( ){
using (var db = new ArticleNetEntities())
{
articles = db.Articles.Where(something).ToList();
}
}
Using this approach you can't use the following code because a.Members is always null( db context is close and cant get data automatically).
var articles = Data.getArticles();
foreach( var a in articles ) {
if( a.Members.any(p=>p.Name=="miki") ) {
...
}
else {
...
}
}
}
Using only a global db context is a bad idea because you must use a delete changes function
in a point of your application yo do this but don't save changes and close the window
var article= globalcontext.getArticleByID(10);
article.Approved=true;
then in another point of application you make some operation and save
//..... something
globalcontext.saveChanges();
in this case previous article approved property is set to modified by entity framework. When you save, approved is set true!!!
Best approach for me is use 1 context per class
You can pass context to another external method if you need
class EditArticle {
private DbEntities de;
private currentAricle;
public EditArticle() {
de = new DbEntities; //inizialize on new istance
}
loadArticleToEdit(Articele a){
// a is from another context
currentArticle= de.Article.Single(p=>p.IdArticle==a.IdArticle){
}
private saveChanges(){
...
pe.saveChanges();
}
}
What you can also do is store your context at a higher level.
E.g., you can have a static class storing the current context:
class ContextManager
{
[ThreadStatic]
public static ArticleEntities CurrentContext;
}
Then, somewhere outside you do something like this:
using (ContextManager.CurrentContext = new ArticleEntities())
{
IEnumerable<Article> article = articleService.GetLatestArticles(true);
}
Then, inside the GetLastestArticles, you just use the same ContextManager.CurrentContext.
Of course, this is just the basic idea. You can make this a lot more workable by using service providers, IoC and such.
You can start preparing Entity Framework from data access layer by creating a generic repository class for all required Entity Framework functions. Then you can used it in Business layer (Encapsulated)
Here are the best practices that I have used for Entity Framework in data, business, and UI layers
Techniques used for this practice:
Applying SOLID architecture principles
Using Repository design pattern
Only one class to go (and you will find it ready)

Categories