Entity framework add a where clause to all queries - asp.net-mvc

I am using Entity framework 5 and using repository pattern. Say I got these entities Customer, Files, Images, Tasks, Invoice, User.
Each entity (apart from Customer) has a foreign key of Customer. When a user logs in I store the customerid in session (aps.net mvc). What I want is any CRUD taken on all entities to be limited to the customer who's user is logged in. e.g I can't afford to delete a Task belonging to customer 1 to be deleted by user who is from customer 2.
Is adding an argument of customerid for each method of repositories the best way to achieve this or are there any better/clever ways of doing it?

Tricky to give a definitive answer but you could make it a bit more extensible by implementing higer order functions, like this:
public interface IRepository<T>
{
public T GetBy(Expression<Func<T, bool>> query)
}
public class FileRepository : IRepository<File>
{
public File GetBy(Expression<Func<T, bool>> query)
{
using(var context = new FilesContext())
{
return context.Files.Where(query).FirstOrDefault();
}
}
}
public class SomeController
{
private IRepository<File> _repo;
public SomeController(IRepository<File> repo)
{
_repo = repo;
}
public ActionResult Index()
{
var model = _repo.GetBy(f => f.CustomerId == Session.Whatever.CustomerId);
return View(model);
}
}
This way you can vary the search query when required, rather than tie yourself in to using a hardcoded customer id property. For example, if you wanted to get the File object by the FileID, not the CustomerID, then:
var model = _repo.GetBy(f => f.FileId == someId);
and that's the only part of the code that needs to change.
Some really good info on Higher Order functions and functional programming in C# here: http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp
Edit:
You might be able to isolate the "Always use the customer ID when hitting DB" into a repository of it's own, using a decorator style pattern, thus: (massive disclaimer - I haven't tested this, but something along these lines should work)
public class SpecialFileRepo : IRepository<File>
{
private readonly IRepository<File> _baseRepo;
public SpecialFileRepo(IRepository<File> baseRepo)
{
_baseRepo = baseRepo;
}
public SpecialFileRepo() : this(new FileRepository())
{
}
public File GetBy(Expression<Func<File, bool>> query)
{
var parameters = query.Parameters;
var newParam = Expression.Parameter(typeof (File), "f");
var additionalQuery = Expression.AndAlso(query.Body,
Expression.Equal(
Expression.PropertyOrField(newParam, "CustomerId"),
Expression.Constant(HttpContext.Current.Session["customerId"])));
var newQuery = query.Update(additionalQuery, parameters);
return _baseRepo.GetBy(newQuery);
}
}
Then anything that's talking to a repository, as far as it's concerned, it's just a base repository, but this class is sitting in between and always grafting the "customerid = sessionwhatever" expression onto what finally gets passed to the database. And of course, anything that only cares about using the base repository, can still do so.

Related

"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.

Onion Architecture - Service Layer Responsibility

I am learning Onion Architecture by Jeffrey Palermo for more than 2 weeks now. I have created a test project by following this tutorial. While studying I came across this question on SO. According to accepted answer, one person nwang suggests that Methods like GetProductsByCategoryId should not be in Repository and one the other hand Dennis Traub
suggests that it is the responsibility of the Repository. What I am doing is :
I have a General Repository in Domain.Interface in which I have a method Find :
public interface IRepository<TEntity> where TEntity : class
{
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> filter = null);
.......
.......
.......
}
Then I created a BaseRepository in Infrastucture.Data:
public class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
internal readonly DbSet<TEntity> dbSet;
public virtual IEnumerable<TEntity> Find(
Expression<Func<TEntity, bool>> filter = null)
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
return query.ToList();
}
}
And I have a concrete repository in Infrastructure.Data
public class ProductRepository : RepositoryBase<Product>, IProductRepository
{
public ProductRepository(MyDBContext context)
: base(context)
{
}
}
Now what I am doing in my Service Layer is Injecting Repository into Service and calling Repository.Find for methods like GetProductsByCategoryId. Like :
public class ProductService : IProductService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IProductRepository _productRepository;
public ProductService(IUnitOfWork unitOfWork, IProductRepository productRepository)
{
_unitOfWork = unitOfWork;
_productRepository = productRepository;
}
public IList<Product> GetProductsByCategoryId(int CategoryId)
{
// At the moment, My code is like this:
return _productRepository.Find(e => e.CategoryId == CategoryId).ToList();
// My confusion is here. Am I doing it right or I need to take this code to
// ProductRepository and call _productRepositoy.GetProductsByCategoryId(CategoryId) here instead.
// If I do this, then Service Layer will become more of a wrapper around repository. Isn't it?
// My question is : What exactly will be the responsibility of the Service Layer in Onion Architecture?
}
}
The way you designed your application is ok... but only if your service will come to handle other things than just wrap up the repository methods!
Always keep in mind the YAGNI principle that says:
Always implement things when you actually need them, never when you just foresee that you need them
Let's say that you have a user story that says that whenever a product description is not found in your DB, you should retreive it from somewhere else (calling an external service or something). Then it seems obvious that your ProductService will have to have a
private readonly IProductRepository _productRepository;
but also a
private readonly IProductDescriptionService _productDescriptionService;
In that situation it really makes sense to add a service layer on top of your repositories.
I find that sometimes things can get over abstracted for the sake of it and offer no real value. I would say that the structure in your example is fine and follows the pattern correctly. Your service layer, correctly, is acting to serve the needs of the client UI, it is loosely coupled to the data layer and contains any business logic needed to manipulate the data.
I always think it is more productive to start simple and build upon your structure than it is to over abstract, over complicate and over bloat a project. A business or technical case will often drive the project, and dictate whether it is needed.
Although, in this case it seems that service later is just a wrapper, sometimes you might have the need to add some business logic or call two repositories. Lets say you have a service called CartService and you have a method called AddToCart in which you need to first get the product, do some calculation and then call insert to another repository like below.
public class CartService : ICartService
{
private readonly IUnitOfWork _unitOfWork;
public CartService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddToCart (int productId, int quantity)
{
var product = _unitOfWork.ProductRepository
.Find(p => p.ProductId == productId).Single();
var cartItem = new CartItem {
ProductId = productId,
Desc = product.Desc,
Quantity = quantiry
};
_unitOfWork.CartRepository.Add(cartItem);
}
}
More, complex scenarios include calling a third party web service etc.

How to convert DTO to View Model and then back again? [duplicate]

This question already has answers here:
Where to convert business model to view model?
(3 answers)
Closed 5 years ago.
I'm using MVC 4 with the repository pattern and unit testing also. I have a typical controller that has simple CRUD functionality. I've separated my View Models from my DTOs and I would like to know the best way to convert between the 2:
Models:
I have Admin.Models.Product which is my view model and AdminAssembly.Models.Product which is my DTO.
Controller:
//repo that handles product operations
AdminAssembly.Interfaces.IEntityRepository<AdminAssembly.Models.Product> db;
//default constructor
public ProductController() { db = new AdminAssembly.Repositories.EntityRepo<AdminAssembly.Models.Product>(new AdminAssembly.Models.EntitiesContext()); }
//unit testing constructor
public ProductController(AdminAssembly.Interfaces.IEntityRepository<AdminAssembly.Models.Product> context) { db = context; }
//
// POST: /Product/Create
[HttpPost]
public ActionResult Create(Admin.Models.Product product) {
if (ModelState.IsValid) {
//COMPILE-ERROR: how to convert to DTO?
db.Add(product);
}
return View();
}
//
// GET: /Product/Edit/5
public ActionResult Edit(int id) {
//COMPILE-ERROR: how to convert to view model?
Admin.Models.Product product = db.GetAll().Where(p => p.ID == id);
return View(product);
}
How do I convert between the 2?
Do I reference my DTO assembly in my view model and do something like: (won't this break my unit testing?)
//convert to AdminAssembly.Models.Product
db.Add(product.ToDTO());
//convert back to Admin.Models.Product via constructor
Admin.Models.Product product = Admin.Models.new Product(db.GetAll().Where(p => p.ID == id));
Do I need some sort of object conversion black box?
Converter.ToViewProduct(product);
Some sort of interface?
or something else?
Update 1:
public static class Product {
public static Admin.Models.Product ToView(AdminAssembly.Models.Product dto) {
Admin.Models.Product viewProduct = new Admin.Models.Product();
//straight copy
viewProduct.Property1 = dto.Property1;
viewProduct.Property2 = dto.Property2;
return viewProduct;
}
public static AdminAssembly.Models.Product ToDTO(Admin.Models.Product viewModel) {
AdminAssembly.Models.Product dtoProduct = new AdminAssembly.Models.Product();
//straight copy
dtoProduct.Property1 = viewModel.Property1;
dtoProduct.Property2 = viewModel.Property2;
//perhaps a bit of wizza-majig
dtoProduct.Property1 = viewModel.Property1 + viewModel.Property2;
return dtoProduct;
}
}
The long-hand response
[HttpPost]
public ActionResult Create(Admin.Models.Product product)
{
if (ModelState.IsValid)
{
//COMPILE-ERROR: how to convert to DTO?
var dtoProduct = new AdminAssembly.Models.Product();
dtoProduct.Property1 = product.Property1;
dtoProduct.Property2 = product.Property2;
//...and so on
db.Add(dtoProduct);
}
return View();
}
While this looks verbose and tedious (and it is) it has to happen eventually, somewhere.
You can hide this mapping either in another class or extension method, or you can use a third party like AutoMapper, as Charlino points out.
As a side note, having two classes with the same name in two different namespaces will eventually get confusing (if not for you, then for the next person who has to maintain your code.) Implement friendlier and more descriptive names wherever possible. For example, put all your view models in a folder called ViewModels, not Models. And append all your view models with ViewModel, or VM. It's also a good convention, imo, to name your view models based on the view that they are for, not so much the domain model that they will be mapped to, as not all view models will map directly to a domain model. Sometimes you'll want parts of more than one domain model, for a single view, and that will blow up your naming convention.
So in this particular case I would suggest changing Admin.Models to Admin.ViewModels and then rename the view model version of Product to CreateViewModel. Your code will be much more readable and will not be littered with namespaces throughout your methods.
All of that would result in a method that would look more like this:
[HttpPost]
public ActionResult Create(CreateViewModel viewModel)
{
if (ModelState.IsValid)
{
var product = new Product();
product.Property1 = viewModel.Property1;
product.Property2 = viewModel.Property2;
//...and so on
db.Add(product);
}
return View();
}
Check out a library called AutoMapper.
From their wiki:
What is AutoMapper?
AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another. This type of code is rather dreary and boring to write, so why not invent a tool to do it for us?
If you dont want to use AutoMapper you may use extensions, as suggested by #Forty-Two. If the number of things to map is no very great, I would go with this approach, just because then, AutoMapper == YAGNI
public static class Extensions
{
public static ViewModel ToViewModel(this Model )
{
var vm = new ViewModel()
{
//map
};
return vm;
}
public static Model ToModel(this ViewModel viewModel)
{
var model = new Model()
{
//map
};
return model;
}
}
Similar to your code in UPDATE, but using extensions instead.

What type of dependency to inject?

I have a specification that validates codes. It looks like the following:
public ClassificationSpecification : ISpecification<Classification> {
HashSet<string> codes;
// constructor elided
public IsSatisfiedBy(Classification classification) {
return codes.Contains(classification.Code);
}
}
The valid codes come out of a Classification table in a database. My question is, which is the better constructor for dependency injection?
public CodeSpecification(IEnumerable<string> codes) {
this.codes = new HashSet<string>(codes);
}
or
public CodeSpecification(IRepository<Classification> repository) {
this.codes = new HashSet<string>(repository.Select(x => x.Code));
}
And the all important question: why?
Your second constructor does real work (via the repository) and this is a bad idea. See http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/
You need to decide if it's valid to load all the values (pass in the values you need to the constructor), or you want to look them up on each call (pass in the repository in the constructor and store it).
I would use this constructor:
private readonly IRepository<Classification> _repository;
public CodeSpecification(IRepository<Classification> repository)
{
_repository = repository;
}
Then, find the valid codes when your class is actually called upon:
public bool IsSatisfiedBy(Classification classification)
{
var _repository.Any(x => x.Code == classification.Code);
}
This ensures that no real work is done until it is needed, separating your application's initialization from its runtime. It also ensures that you are always working with fresh data in IsSatisfiedBy; caching the values in the constructor introduces a period of time where the codes in the repository might change.
If the number of codes is large, and the repository won't execute the Any efficiently, you may still want to implement caching. It is a good idea to follow the same advice and not cache until the first call to IsSatisfiedBy:
private readonly HashSet<string> _codes;
private readonly object _codesSync = new object();
public bool IsSatisfiedBy(Classification classification)
{
if(_codes == null)
{
lock(_codesSync)
{
if(_codes == null)
{
_codes = new HashSet<string>(_repository.Select(x => x.Code));
}
}
}
return _codes.Contains(classification.Code);
}
Constructors in dependency-injected objects are infrastructure elements; domain logic of any kind should generally be deferred until the object is invoked by another.

Using Stored Procedures with Linq To Sql which have Additional Parameters

I have a very big problem and can't seem to find anybody else on the internet that has my problem. I sure hope StackOverflow can help me...
I am writing an ASP.NET MVC application and I'm using the Repository concept with Linq To Sql as my data store. Everything is working great in regards to selecting rows from views. And trapping very basic business rule constraints. However, I'm faced with a problem in my stored procedure mappings for deletes, inserts, and updates. Let me explain:
Our DBA has put a lot of work into putting the business logic into all of our stored procedures so that I don't have to worry about it on my end. Sure, I do basic validation, but he manages data integrity and conflicting date constraints, etc... The problem that I'm faced with is that all of the stored procedures (and I mean all) have 5 additional parameters (6 for inserts) that provide information back to me. The idea is that when something breaks, I can prompt the user with the appropriate information from our database.
For example:
sp_AddCategory(
#userID INT,
#categoryName NVARCHAR(100),
#isActive BIT,
#errNumber INT OUTPUT,
#errMessage NVARCHAR(1000) OUTPUT,
#errDetailLogID INT OUTPUT,
#sqlErrNumber INT OUTPUT,
#sqlErrMessage NVARCHAR(1000) OUTPUT,
#newRowID INT OUTPUT)
From the above stored procedure, the first 3 parameters are the only parameters that are used to "Create" the Category record. The remaining parameters are simply used to tell me what happened inside the method. If a business rule is broken inside the stored procedure, he does NOT use the SQL 'RAISEERROR' keyword when business rules are broken. Instead, he provides information about the error back to me using the OUTPUT parameters. He does this for every single stored procedure in our database even the Updates and Deletes. All of the 'Get' calls are done using custom views. They have all been tested and the idea was to make my job easier since I don't have to add the business logic to trap all of the various scenarios to ensure data quality.
As I said, I'm using Linq To Sql, and I'm now faced with a problem. The problem is that my "Category" model object simply has 4 properties on it: CategoryID, CategoryName, UserId, and IsActive. When I opened up the designer to started mapping my properties for the insert, I realized that there is really no (easy) way for me to account for the additional parameters unless I add them to my Model object.
Theoretically what I would LIKE to do is this:
// note: Repository Methods
public void AddCategory(Category category)
{
_dbContext.Categories.InsertOnSubmit(category);
}
public void Save()
{
_dbContext.SubmitChanges();
}
And then from my CategoryController class I would simply do the following:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
var category = new Category();
try
{
UpdateModel(category); // simple validation here...
_repository.AddCategory(category);
_repository.Save(); // should get error here!!
return RedirectToAction("Index");
}
catch
{
// manage friendly messages here somehow... (??)
// ...
return View(category);
}
}
What is the best way to manage this using Linq to Sql? I (personally) don't feel that it makes sense to have all of these additional properties added to each model object... For example, the 'Get' should NEVER have errors and I don't want my repository methods to return one type of object for Get calls, but accept another type of object for CUD calls.
Update: My Solution! (Dec. 1, 2009)
Here is what I did to fix my problem. I got rid of my 'Save()' method on all of my repositories. Instead, I added an 'Update()' method to each repository and actually commit the data to the database on each CUD (ie. Create / Update / Delete) call.
I knew that each stored procedure had the same parameters, so I created a class to hold them:
public class MySprocArgs
{
private readonly string _methodName;
public int? Number;
public string Message;
public int? ErrorLogId;
public int? SqlErrorNumber;
public string SqlErrorMessage;
public int? NewRowId;
public MySprocArgs(string methodName)
{
if (string.IsNullOrEmpty(methodName))
throw new ArgumentNullException("methodName");
_methodName = methodName;
}
public string MethodName
{
get { return _methodName; }
}
}
I also created a MySprocException that accepts the MySprocArgs in it's constructor:
public class MySprocException : ApplicationException
{
private readonly MySprocArgs _args;
public MySprocException(MySprocArgs args) : base(args.Message)
{
_args = args;
}
public int? ErrorNumber
{
get { return _args.Number; }
}
public string ErrorMessage
{
get { return _args.Message; }
}
public int? ErrorLogId
{
get { return _args.ErrorLogId; }
}
public int? SqlErrorNumber
{
get { return _args.SqlErrorNumber; }
}
public string SqlErrorMessage
{
get { return _args.SqlErrorMessage; }
}
}
Now here is where it all comes together... Using the example that I started with in my initial inquiry, here is what the 'AddCategory()' method might look like:
public void AddCategory(Category category)
{
var args = new MySprocArgs("AddCategory");
var result = _dbContext.AddWidgetSproc(
category.CreatedByUserId,
category.Name,
category.IsActive,
ref args.Number, // <-- Notice use of 'args'
ref args.Message,
ref args.ErrorLogId,
ref args.SqlErrorNumber,
ref args.SqlErrorMessage,
ref args.NewRowId);
if (result == -1)
throw new MySprocException(args);
}
Now from my controller, I simply do the following:
[HandleError(ExceptionType = typeof(MySprocException), View = "SprocError")]
public class MyController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Category category)
{
if (!ModelState.IsValid)
{
// manage friendly messages
return View(category);
}
_repository.AddCategory(category);
return RedirectToAction("Index");
}
}
The trick to managing the new MySprocException is to simply trap it using the HandleError attribute and redirect the user to a page that understands the MySprocException.
I hope this helps somebody. :)
I don't believe you can add the output parameters to any of your LINQ classes because the parameters do not persist in any table in your database.
But you can handle output parameters in LINQ in the following way.
Add the stored procedure(s) you whish to call to your .dbml using the designer.
Call your stored procedure in your code
using (YourDataContext context = new YourDataContext())
{
Nullable<int> errNumber = null;
String errMessage = null;
Nullable<int> errDetailLogID = null;
Nullable<int> sqlErrNumber = null;
String sqlErrMessage = null;
Nullable<int> newRowID = null;
Nullable<int> userID = 23;
Nullable<bool> isActive=true;
context.YourAddStoredProcedure(userID, "New Category", isActive, ref errNumber, ref errMessage, ref errDetailLogID, ref sqlErrNumber, ref sqlErrMessage, ref newRowID);
}
I haven' tried it yet, but you can look at this article, where he talks about stored procedures that return output parameters.
http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx
Basically drag the stored procedure into your LINQ to SQL designer then it should do the work for you.
The dbContext.SubmitChanges(); will work only for ENTITY FRAMEWORK.I suggest Save,Update and delete will work by using a Single Stored procedure or using 3 different procedure.

Resources