Where to store methods that relate to the model - c#

I hope this hasn't been answered already, but I don't even know what to search for.
I have an MVC project, and I need to return a list of users from the DB. Simple enough. But I only want to return certain users. Again, simple stuff.
What has me confused is that I don't know where I should put the code for that. If I put it in the controller I end up with the same code in multiple methods, and spread over multiple controllers.
I've currently put the method to return the users in my dbcontext class. That works and seems to make sense, but I wonder if there's a better way to do it? That class would end up getting massive in a bigger project.
I've looked at using repository classes, but that just seems to be adding an additional layer. I'm using EF6, and not doing any unit testing (yet)
The code below shows the structure of my dbcontext class (I've edited out the actual code, to keep it brief).
public class LeadsDB :DbContext
{
public LeadsDB()
: base("Leads")
{
}
public DbSet<User> Users { get; set; }
public IEnumerable<SelectListItem> GetUserList(bool includeBlank = true)
{
return UserList;
}
}

As they say:
All problems in computer science can be solved by another level of indirection... Except for the problem of too many layers of indirection.
So depending on the size and scope of your app, you need to decide how many layers of indirection will let you hit the sweet spot of maintainability for your application.
If your application is going to be really small, go ahead and put those methods on your context directly. If it's going to be big enough for your DbContext to become unmaintainable, I'd create repositories. And so forth.
In the application I'm working on, we only interact with Entity Framework for data-related operations. All of our repositories return DTOs which are abstractions of our data model. Our Controllers further convert most of our DTOs into ViewModels before passing them to the Views. And there's a "Manager" layer between the controllers and the repositories to handle business logic and security-checking. We end up with a lot of layers, but we've found value in decoupling the view, presentation, business, security, and data models.

This looks like an Entity Framework DBContext; if so, then use this as your Data Layer.
Possibly consider using a "Business Layer" abstraction model to do additional things to your objects. Your data access layer should do just that: work with data.
If you have, say, a singleton class as your business layer, then you could use your data layer to directly work with the data, and then the business layer to apply business logic to that data and return it to your presentation layer (be it a website, a windows form, etc.)
The business logic layer could possibly check for the data in cache and if it doesn't exist, then retrieve it from your data layer, put it in cache and return it to your presentation layer.

Related

What is the standard I should use in MVC coding

Based on the answers mentioned here, I understood that I should put the business logic inside the model itself, while in my program I am using EF directly inside the actions of the controller for example to get the list of cars from the database directly I am doing the following:
public ActionResult CarList()
{
using(var _db = new CarRentEntities())
{
var result = _db.Cars.Where(m=>m.Active);
return View(result);
}
}
what is the impact on my website performance if I will use the mentioned above code inside controller or inside Model?
which method I should use? for example if I want to work with a team, is there a standard I should follow to separate the code, kindly advise
for using the repository pattern: I read that we should not use if as mentioned for example here , i will copy some of what mentioned:
The single best reason to not use the repository pattern with Entity
Framework? Entity Framework already implements a repository pattern.
DbContext is your UoW (Unit of Work) and each DbSet is the repository.
Implementing another layer on top of this is not only redundant, but
makes maintenance harder.
if my database contains the following tables: Manufacturers , Cars , Rent , Clients , rent class is the a table with 2 foreign keys between Clients and Cars and contains other detailed fields.
how to deal with Rent Object which need to get data from 2 different repositories Cars and Clients in order to display the renting grid based on search criteria entered by the user, if I will use the repositories Cars and Clients , they have their own dbContext, BOOM my head cannot understand this technique, kindly advise
The answer to your question is, it does not really affect performance but it will definitely become an issue in terms of maintainability as the application grows bigger. You can adopt the SOLID architecture principles: SOLID architecture principles using simple C# examples. This enables you to develop high quality software.
You can create a multi-layered application:
Interface Layer - MVC application
Business Layer - Class Library with classes with logic
Data Access Layer - Database Contexts and Repositories, unit of work with CRUD operations
Shared layer - Logging, AppSettings, validations, utilities, extensions, constants, enums
Having your application in this structure would require you to consider things like inversion of control, dependency injection and many more to ensure loosely coupled classes, easy unit testing and most of all a solid application.
You can also read this: Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application
Generally the Model is a "unit" - i.e. it is a model of the data you want to display. The Controller is an "integrator" - i.e. it pulls together the various resources required to render your web page. You may wish to create a database fascade class which does something like this;
public ActionResult CarList()
{
using(var carStore = new Factory.CreateCarStore())
{
var result = carStore.GetActiveCars();
return View(result);
}
}
To separate your database access from your web controller (this would make it more test-able as well because you can substitute a different CarStore implementation (i.e. a Test XML data set) for testing purposes.

How do you implement a business logic layer when using entity framework as data access layer?

Say i have 3 layers
layer 1: WPF Project (contains: xaml, viewmodels, mvvm framework)
layer 2: business logic layer (contains: plain c# classes)
layer 3: entity framework (contains: repository/data access classes)
when you dont want to expose your DAL(layer 3) to View(layer 1)
how do you implement the business logic layer well?
im having a hard time putting values back and forth the BLL objects and DAL entities.
can you please help?
Entity Framework doesn't work really well in a "disconnected" model. Unless something has changed, I've never been able to get it to work great easily.
You could use AutoMapper in Layer 2 to create ViewModels to present to Layer 1, but then you'd still have to send the changes back to Layer 3, which could be a pain.
If you're only developing a small app that will not change in the foreseeable, then just do whatever is quickest now. If you want a long-term maintainable app, then let me put forth the following.
The problem with this vertical layer approach is that whenever you need something in the view, you will have to add it to both the Business Layer (even if the business layer doesn't care about it), and the Data Layer. This requires your business layer to look like 1) UI views of the data 2) business views of the data and 3) the database representation of the data. That and/or you need a lot of mapping in-between layers. All of which dilutes business layer's actual purpose of representing business logic. What tends to happen then is that all the business logic gets migrated into transaction methods (that could just as well be static methods) to just change states on data objects. There's nothing at all wrong with that if your problem domain is nothing but CRUD with no complex logic. With complex logic, such business methods can get pretty tricky or even have undefined outcomes (because complex interdependencies on "fields" can be contradictory and hard to resolve).
Assuming you have complex logic, user views of data and business representations of data are often very different, and so UI views end up with specialized models of the data. If I were you, I just embrace this and use a simple version of the CQRS principle. That is, have the data for your UI views come from a different place than where your business operations are executed. In your case, I might have an EF Model in your DAL that only services your UI views, and gives them exactly what they need (whether by database views, stored procedures, or pre-compiled report tables). Then create a separate EF model that services only the needs for your Business entities. Then when you are ready to perform an actual business action, the UI's viewmodel action method can load the business object from the business EF model (or better yet, call an object factory from the business layer which does this) and run an appropriate action on the business object. Note that I'm also making the assumption here that your database is highly relational (mostly 2nd and 3rd normal form) and you are set on using EF.
I would not try to make your View Models into business logic. This makes your business logic not easily reusable on other platforms or applications (like web). MVVM should only service the UI. In my mind, the V (view) represents what the user sees and operates. The M (model) represents what the user chose on that view. And the VM (view model) translates between the two. Your program should then take the user's validated choices (UI model) and extract the needed data out of it to perform an appropriate business operation.
Instead of exposing all of your DAL to View Layer, just exchange your domain objects (EF objects) between all layers. The structure may be similar to the following:
Presentation Layer-------- ^
BLL --------------------------- | Data objects
DAL (Repositories etc.)--- |
So, all of your layers will be disconnected; but they will share the same domain objects. In real world, you can implement a similar structure by creating a seperate dll for Entity Framework entities which is shared by all layers. Note that ObjectContext shall be only visible to DAL (by default, entities and object context are generated in the same dll, you need to seperate this into two dlls).
In addition to the answer by Daryal, you can define your business-objects in your BL to be POCO's, and use EF in your DAL layer to read them from or persist them to the database.
If you define an repository-like interface in your BL (or unit-of-work, whatever naming you give it), and implement the interface in your DAL, then all you need is a little DI to get an instance of the repository-class without having to reference the DAL all the time. It works like a charm for me.
See here and here for more information.
Your ViewModels are your application in MVVM, so they should be handling things like data access through your Repository classes, or business logic (either directly, or indirectly using your validation classes).
If you don't want to directly reference the classes, use an Interface but be aware that you'll need to have some way of passing your inherited class to your ViewModel. I once did a project where we had a library of shared interfaces, such IRepository interfaces, and everything was imported/exported using MEF so the layers didn't reference each other directly.
The final (simplified) layout was:
Models -> Contained plain data objects that could do simple validation on their own data (length, min/max values, etc) but that didn't do any advanced validation or business logic. Did not reference any other library.
Common -> Contained interfaces, utilities, and other commonly shared classes. Referenced the Model library only.
DAL -> Contained Data Access and Repositories based on repository interfaces found in Common library. Referenced Common library for interface definitions and utilities, and Model library because it contained the data models used or returned in data access calls
ViewModels -> Contained application and business logic. Referenced Common for its utilities and interfaces, and Models for the data models
Client -> Contained Views. Referenced Models and ViewModels so it could write DataTemplates for both object types
Entity framework is suppouse to be used as "Logic Layer" by itself.
Your idea may have some sense, to use combine technologies.
Howevere, I think some of those Micros. libraries, where designed to be used separately, unless, otherwise explicitly combined & mentioned in their websites.
Good Luck.
I second daryal and I have implemented this in some projects. It is absolutely OK to use POCO as business objects.
Another approach instead of creating 2 projects (one for DB Context and one for Entities) is to use one DAL/DATA project only and reference it in BLL. Then inherit the POCO class in BLL and use that class in UI layer. Below is the basic sample code:
// assume this is EF generated POCO
namespace Owner.Project.Data{
public partial class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
}
// this is manually created class in BLL
using Owner.Project.Data;
namespace Owner.Product.Business{
public class StoreProduct : Product {
public bool Add (string productName){
// TODO - add product using EF as you normally do
}
}
}
Now you can reference the BLL in your UI project and use StoreProduct class there. To achieve loosely coupled pattern, Of course you could also inherit the StoreProduct class from an IStoreProduct interface and make use of it in UI or web service but that is another topic.

What is the right way to create an object that can be passed around to different layers

I am new to programming so sorry i am not clear on things
I created a class let say
public class Users
{
public int ID { get; set; }
}
My first question is where should i put this class in term of the 3 layer design
If i put it in the Business layer, when i need to update the data access layer i would like to pass the Users object to Data access layer like this
sendDataToDB(List<Users);
on the data access layer, VS would generate this method for me
public static void sendDataToDB(List<global::BLL.Users> newUsers)
{
}
But there would be error saying:
The type or namespace name 'BLL' could not be found in the global
namespace (are you missing an assembly reference?)
Right now i just create another library that contain the Users object and give all three layers access to that library.
I really dont think that is the right way to do things. So any suggestion would be great
If your User object just contains data and no behavior it seems to be a data object which bundles data related to user. In this case it's a data object and can be passed across layers. You could probably create a separate namespace or even assembly for that.
See: http://en.wikipedia.org/wiki/Data_Transfer_Object
The rules of Layering is that lower layers can know nothing of higher layers. For all three layers to see a particular class, it has to be in the lowest layer. This generally means the data access layer--which "Users" may be more of a Business concern.
The other problem with layers is you don't generally pass-along dependencies that a lower layer has to it's upper layers (at least dependencies on other layers). e.g. a business layer that depends on a data layer generally shields the data layer from the layer about the business layer...
This really means that classes that need to be shared between all layers should be outside of the three layers.
I recommend having a Business class AND a Data class. the Business layer knows how to get the Data class and translate it into a business class for higher layers. e.g. you may have Data.Users that you use to query/update data in a database. The Business layer uses that to query/update to the database and translates it into Business.Users that is then given to higher layers...
Some useful layering interaction rules: http://msdn.microsoft.com/en-us/library/ee658109.aspx#Step5
This is a really good question, and one of those issues where I still think "it's 2012 , why is this still so hard?".
So, you have a 3 tier solution: User Interface, Domain / Business Logic, Data / Persistence. In an ideal world you want to be able to display your User class in the UI, define the User class and it's logic in the BL and be able to pass it to a Data repository to be saved to the database. Unfortunately you can't do this with 3 tiers because of circular dependencies.
A common solution is to use something like AutoMapper so each tier has it's own version of (for example) User class, and you just map between like object in tiers. A tool like AutoMapper allows your Complex Domain Model to be mapped to a simpler UI display type class. The Domain Object (even if it is made of other objects) can then be mapped to the type of object that it's specific repository requires - again using AutoMapper (you don't have to use AutoMapper by the way, it just makes the mapping less dull).
Another option is to perhaps break out of three tiers, and have a fourth 'DTO' tier available 'horizontally' to each 'vertical' layer. I tend to map them though.
New versions of EF put the classes created by EF all the way into the UI View, but this just feels wrong to me and is not what I know about, but might work for you?
I'm sure other people will have other suggestions too. I'll watch this one with interest.

Few questions regarding BLL and DAL in my first 3-tier Winform Application

I am trying to create 3-tier winform application. Since this is my first attempt of 3-tier design, I got stuck and have few questions.
The application will support attaching multiple sqlite db files.
So I created class like this
public class Database
{
public string Name { get; set; }
public string FilePath { get; set; }
public bool isAttached { get; private set; }
}
Now I want to have collection of those objects.
Should I create another class like DatabaseList below or is enough to just create a List
public class DatabaseList : List<Database>
{
...
vs
List<Database> myDatabases;
What should be created in Form1.cs?
For example I assume the collection above should be created in BusinessLayer and not in Form1.cs and only BusinessLayer class is created in Form1.cs. Is this correct?
Where to put Attach Method?
The method would be like this:
public void AttachDB(Database db)
{
MySqliteHelper.Attach(db.Name, db.FilePath);
this.Add(db);
}
Do I put the method in DatabaseList class (if this is the way to create collection) or should it be in BusinessLayer?
How to make the Attach method to support additional relational databases like MS SQL Compact Edition which also resides in a single file
I was thinknig of creating another general database helper class with same methods as MySqliteHelper and the AttachDB method would call that instead. Something like
MyDBHelper.Attach(db.Name, db.FilePath);
Or is this where Dependency Injections like Ninject can be helpful? I never used that before and all I am recalling from Ninject is a samurai having different weapons so it seems to me to be kinda similar to my problem having different specific database classes.
I'm going to tackle this question in parts because it covers a lot of ground.
What qualifies as a 3-tier architecture?
A 3-tier (or n-tier, tiered) architecture is basically any design where the interface doesn't directly communicate with the database, no matter how thin the actual tiers are. You could create a single class with functions to get and save data, and it would still qualify as a 3-tier architecture. That being said, what I'm going to explain below is probably the most common implementation of a 3-tier architecture.
Layer vs. Tier: What's the difference?
To understand the 3-tier architecture, it's important to first make a distinction between a layer and a tier. An application can have many physical layers and still contain only three logical tiers. If a picture really is worth a million words, the diagram below should clear that up for you.
In the diagram above, the Business/Middle Tier is comprised of business logic, business objects, and data access objects. The purpose of this tier is to serve the middle man between the user interface and the database.
The Data Access Layer (DAL)
The data access layer is comprised of a data access component (see below) and one or more data access objects. Depending on the need, the data acess objects are usually set up one of two ways:
One Data Access Object for each Business Object
One Data Access Object shared by many Business Objects
It sounds like you're going to be dealing with several databases, so it would probably make sense to go with the one-to-one option. Doing it this way you'll have the flexibility to specify which database/connection corresponds to which business object.
Data Access Component
Your data access component should be a very generic class containing only the bare-bones methods needed to connect and interact with a database. In the diagram above, that component is represented by the dbConnection class.
Questions & Answers
What should be created in Form1.cs?
The only thing the front end deals with are the business objects and the business logic. Sometimes it's not that black and white, but that's the idea.
Where to put Attach Method?
Instead of an Attach method, pass a connection string into your data access component. A connection string can be used to attach and/or connect to pretty much any database.
How to make the Attach method to support additional relational databases like MS SQL Compact Edition which also resides in a single file?
See above.
Should I create another class like DatabaseList below or is enough to just create a List?
Honestly, this is up to you and doesn't affect the validity of the 3-tier architecture. You know the specific requirements that you're trying to meet, so do it if it makes sense. Give consideration to how your Data Access Object(s) will interact with this class though, because you will need to expose the methods for executing queries and non-queries on whatever database is selected from the list.
What you lack is thinking in terms of objects and their responsibility.
What object is responsible for creating instances of your database descriptions? Should it be Form1?
The OOP tells you that if you have such doubts you can follow the Pure Fabrication principle and just create another class to be responsible for this. This is just as simple.
So you can create a class, let call it DatabaseManager, put your list of databases there plus the Attach method. You probably also want this manager to be an ambient class (the same instance shared among other classes) so you can build a Singleton out of it (but this is not necessary).
DI containers could probably help you to organize services and manage their lifetime but I recommend you start with a good book on this before you misuse the idea. Mark Seemann's "Dependency Injection in .NET" is fine.
You need to think in terms of modularity and abstraction. See you have multiple entities to be passed across layers.
Following are the examples:
1. Presentation will create an object of business layer or business facade. But it will expect the logical entity from business layer.
Business layer will create the object of DataAccess and will expect the logical entity from DataAccess to perform business operations.
DataAccess will do whatever it would like to do to get the information from database. So if you need to connect the oracle / sql /sqllite / files system whatever but it will convert or say initialize the Logical entity (entity is a Class only consisting of properties).
So every layer will have their own responsibility and perform the operation it is responsible for.
So I think your db related operations will go in DataAccess.

Please help on choosing the right arhitecture of n-tier web application

Please help on choosing the right way to use the entities in n-tier web application.
At the present moment I have the following assembleis in it:
The Model (Custom entities) describes the fields of the classes that the application use.
The Validation is validating the data integrity from UI using the reflection attributes method (checks data in all layers).
The BusinessLogicLayer is a business facade for additional logic and caching that use abstract data providers from DataAccessLayer.
The DataAccessLayer overrides the abstarct data providers using LinqtoSql data context and Linq queries. And here is the point that makes me feel i go wrong...
My DataLayer right before it sends data to the business layer, maps (converts) the data retrieved from DB to the Model classes (Custom entities) using the mappers. It looks like this:
internal static model.City ToModel(this City city)
{
if (city == null)
{
return null;
}
return new model.City
{
Id = city.CountryId,
CountryId = city.CountryId,
AddedDate = city.AddedDate,
AddedBy = city.AddedBy,
Title = city.Title
};
}
So the mapper maps data object to the describing model. Is that right and common way to work with entities or do I have to use the data object as entities (to gain a time)? Am I clear enough?
You could use your data entities in your project if they are POCOs. Otherwise I would create separate models as you have done. But do keep them in a separate assembly (not in the DataAccess project)
But I would not expose them through a webservice.
Other suggestions
imho people overuse layers. Most applications do not need a lot of layers. My current client had a architecture like yours for all their applications. The problem was that only the data access layer and the presentation layer had logic in them, all other layers just took data from the lower layer, transformed it, and sent it to the layer above.
The first thing I did was to tell them to scrap all layers and instead use something like this (requires a IoC container):
Core (Contains business rules and dataaccess through an orm)
Specification (Seperated interface pattern. Contains service interfaces and models)
User interface (might be a webservice, winforms, webapp)
That works for most application. If you find that Core grows and becomes too large too handle you can split it up without affecting any of the user interfaces.
You are already using an ORM and have you thought about using a validation block (FluentValidation or DataAnnotations) for validation? Makes it easy to validate your models in all layers.
It may be a common practice to send out DTOs from serivce boundary (WCF service, etc.) but if you are directly using your "entities" in your presentation model, I don't see any benefit in doing that.
As to the code snippet you have provided, why not use AutoMappter? It helps by eliminating writing of boiler-plate mapping codes and does that for you if you have a set of convention in place.
Get rid of the model now, before removing it later will require refactoring the whole application. The last project i worked on used this architecture and maintaining the DTO layer and mappings to the database model layer is a huge pain in the arse and offers no usefull benefits. One of the main things that is anoying is that LinkToSql does not effectively support a disconnected data model. You cannot update a database table by creating a new DB entity with a primary key matching an existing record and then stick it into the data context. You have to first retrieve the entity from the database, update it then commit the changes. Managing this results in really nasty update methods to map all the properties from your DTOs to your LinqtoSql classes. It also breaks the whole deferred execution model of LinqToSql. Don't even get me started on the problems it causes with properties on parent classes that are collections of child DTOs (e.g. a customer DTO with an Orders property that contains a collection of order DTOs), managing those mappings is really really fiddly, i had to do some extensive optimisations because retrieving a few hundred records ended up causing LinqToSql to make 200,000 database calls (admittedly there was also some pretty dumbass code as well but you get the picture).
The only valid reason to use DTOs is if you want to have multiple pluggable Data Access Layers e.g. LinqToSql and NHibernate for supporting different DB servers. That way you can swap out the data access later without having to change any other layers. If you don't need to do this then save yourself a world of pain and just use the LinqToSql entities.

Categories

Resources