I am using Entity Framework code first in a test project. I have distributed code in different layers as below
Model Layer
This layer is reference in all other layers/projects
namespace Model
{
Public class Sample
{
Public string Name
[ForeignKey("Category")]
public int CatrgoryId
Public Category Category
}
}
DAL
namespace DAL
{
public class SampleContext:DbContext
{
...
}
}
In DAL I only have the context class and migrations
BLL
namespace BLL
{
public class SampleBLL
{
public List<Sample> GetAll()
{
retrn new SampleContext().Samples().ToList()
}
}
}
UI
namespace UI
{
public class UIHelper
{
public List<Sample> GetSamples()
{
return new SampleBLL().GetAll();
}
}
}
It does not seem practical to use EF entity model objects in UI as they might have navigation properties and cannot be directly bound to controls like DataGridView because in that case the datagridview will have both the CategoryId and Category columns while I need to display the Category Name as Category eg DataGridView.DataSource = new SampleBLL().GetAll()
One solution that I could think of is to use ViewModel classes and manually map the entity model objects to viewmodel objects in BLL and return viewmodel objects to UI, But, introducing a new layer ViewModel would mean replicating all my Model objects with minor changes.
Forexmple the view model for above sample model would
namespace Model
{
Public class Sample
{
Public string Name
public int CatrgoryId
public string CategoryName
}
}
Is the viewmodel layer only option I have or there is an other efficient way to consume the Entity Models directly in UI.
It is a very bad idea to use Entity Models directly in UI, mainly because of the issues you've exposed. More importantly, you're currently only retrieving data and displaying it "as is", but the slightest change in UI affects DB, and vice-versa. Any more complexe logic would be very troublesome to implement, AFAIK
At work, we use a Transport namespace to store classes corresponding to our entities and assemblers methods to convert entities to transport classes once we're done with retrieval logic. This way we're separating model from controller, and can safely manipulate data without any risk of unwantingly affecting the database.
Related
I don't know what kind of object I should pass from DAL to BLL if I need to create custom type.
In DAL I have an entity:
public class Note
{
[Key]
public int NoteId { get; set; }
[Required]
[Column(TypeName = "varchar(MAX)")]
public string Content { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
But I need to return to BLL only: NoteId, Content and number of comments which aren't spam so in DAL I have a query:
public IEnumerable<WhatIsIt> GetNotesWithNoSpamCommentsCount()
{
var whatIsIt = context.Notes.Select(x =>
new WhatIsIt
{
NoteId = x.NoteId,
NoteSummary = x.Content,
NoteCommentsCount = x.Comments.Where(y => y.IsSpam == false).Count()
}).ToList();
return whatIsIt;
}
What kind of object is it which I return - is it Data Access Object or Model or Data Transfer Object or Business Object or something else?
As per the code you've written, it could be your DTO(Date transfer object).
I assume here that Note is your entity class. So, it wouldn't best practices to use entity class to transfer the data between layers.
You can use DTO object to transfer data with required properties only. But again keep in mind, your viewpage need a model class to bind the data. So you've to map your DTO to your entity class with using AutoMapper or other library.
Hope this helps!
Model and DTO can be different. Both are used for different purpose. Here in your context I think you should create a new DTO (model)object which will contain only the required fields that you need to send from DAL to BAL. It will be more secure and faster as it will carry less data.
I see you are only concerned about WhatIsIt that is striped down version of Note and will be the result of your DAL query. I have different opinion on this i.e. WhatIsIt should not be part of and thus returned from DAL to BLL. I will come back to this in a moment. Before that let's revise few terms.
Domain / Business object - They are usually same and include business logic.
Domain object / DTO - If business logic is performed outside of domain object then that object can be considered to be DTO that has nothing but properties and is used for data transfer across layers.
Entity vs DTO - Entity is purely part of data model and are used by ORMs or data access layer in general to work with data stores.
Now back to the point I made earlier - "WhatIsIt should not be part of and thus returned from DAL to BLL". To me WhatIsIt is a DTO that will be created by BLL once it gets the Entity object back from DAL (you already have referenced DAL in BLL so this should not be a problem). And then BLL will pass this DTO up to the presentation layer, ViewModel to be specific, if applicable.
A few queries on EF.
Questions -
Should the methods that directly use database context object be part of Controller classes or Models?
ContactManagerContext.cs (which I am considering as a DAL layer?) Is my assumption correct?
Where should the ContactManager class be placed? Model or DAL? It is currently part of the Model class.
will add more questions
This is how I have structured the classes - Models and Controllers.
Please review and comment on if the code is structured correctly or not and how it can be improved.
Model class (Contact.cs):
using Contact_Manager.DAL;
namespace Contact_Manager.Models
{
public class Contact
{
[Key]
public int ContactId { get; set; }
[Required, MaxLength(100)]
public string FirstName { get; set; }
[Required, MaxLength(100)]
public string LastName { get; set; }
public string EMail { get; set; }
public string Phone { get; set; }
public string BusinessName { get; set; }
}
public class ContactManager
{
ContactContext db = new ContactContext();
public IEnumerable<Contact> ContactList(int? selectedContact)
{
IQueryable<Contact> contacts = db.Contacts;
return contacts.ToList();
}
}
}
ContactManagerContext.cs (DAL)
------------------------------
using System.Data.Entity;
using System.Linq;
using Contact_Manager.Models;
namespace Contact_Manager.DAL
{
public class ContactContext : DbContext
{
public ContactContext()
: base("ContactMgrDBContext")
{
Database.SetInitializer<ContactContext>(new DropCreateDatabaseIfModelChanges<ContactContext>());
}
public DbSet<Contact> Contacts { get; set; }
}
}
ContactController.cs (Controller class):
using System.Web.Mvc;
using System.Linq;
using Contact_Manager.Models;
namespace Contact_Manager.Controllers
{
public class ContactController : Controller
{
//
// GET: /Contact/
public JsonResult ContactList()
{
ContactManager cMgr = new ContactManager();
IEnumerable<Contact> contactList = cMgr.ContactList(0);
//var contactsJson = JsonConvert.SerializeObject(contacts.ToList());
return Json(contactList, JsonRequestBehavior.AllowGet);
}
public ActionResult Index()
{
return View();
}
}
}
The MVC pattern is one of the most misunderstood architecture patterns.
Also if it is used very often in UI it is a more general approach. The common usage has to be separated from the aim to adress different responsibilities.
The best way to explain MVC is to see it as a pattern that separates responsibilities AND the collaboration between them in ONE layer. So you may have MVC in the UI-Layer, but also in the DAO-Layer.
For example in the UI-Layer a model object is an object that holds the state of a UI-Component. The View-Object is the UI-Component that holds logic to draw itself on base of the model object state. The Controller retreives events from different sources and orchestrates communication between model and view.
In the DAO-Layer the model object is a part of a database state (often a row). Think of an ORM-Object. The view object is the representation for the "next" layer. The controller is the DAO that orchestrates mappings and changes.
In general you need something that holds a STATE (model). Then you need an external representaion of the STATE to PUBLISH (view) avoiding coupling to the STATE. After all you have to have BEHAVIOUR (controller) orchestrate changes and mappings.
The approach to see MVC as layers may work for small projects. In larger projects you will face problems in maintainability because you have definitely MORE than three responsibilities. And if you only have three layers you will mix responsibilities lacking the Single Responsibility Principle.
To answer your questions:
No. Write a separate DAO for that. The controller and/or the model should use that.
No. See 1.
If we talk about MVC the controller is the controller. Nothing else. If we talk about layers the controller seems to mix responsibilities of UI, Model maybe DAO. So the assignment is ambiguous.
You can you the three Layers' model in the Controller part. the Controller will be the highest layer, and it will "talk" with the BL and so on.
The Models suppose to be simple and clean.
I've got a situation where I have data classes that are generated by a database with various properties on them e.g which I cannot modify.
public DataClass
{
public string PropertyX {get; set;}
public int PropertyY {get; set;}
public float PropertyZ {get; set;}
}
Some of these classes may have 20 or so properties. When updating the data a "transient" copy of the "persistent" data is made, then the properties updated on the transient and copied from the transient to persistent.
Which is fine although if only changing one property isn't very efficient.
I wanted to find out if there is a way in c# that I could create a list of flagged properties or add attributes onto certain flagged properties I wish to update.
So the end result would be (please note this is all pseudo)
DataClass transientObj = new DataClass(Transient);
[FlagPropertyToUpdate] //This is the bit I have no idea how to do
transientObj.propertyX = "updateOnlyMe!";
DataClass persistantObj = new DataClass(Persistant);
UpdateData dataUpdater = new UpdateData(transientObj,persistantObj)
dataUpdater.save();
public UpdateData
{
public void save(){
//some how know to only update propertyX and not all three properties
}
public UpdateData(DataClass trans, DataClass pers)
}
Any assistance on how I could go about doing this (and if its possible) would be highly appreciated!
I'd recommend creating a DTO (Data Transfer Object) that supports dirty-flagging the relevant properties. That way your classes can remain unchanged. Have a look at Automapper.
Then again, I'd invite you to reconsider your assertion that updating the complete set of properties is inefficient, assuming they're simple types. Writing to an entire row in a database is generally no more expensive than writing a single column. I'd be more concerned wth concurrency in the situation you describe.
I think View Model's will fit here.
The ViewModel is an abstraction of the View or a conceptual state of the data as opposed to the real state of the data in the Model.
So in this case you will have a class like:
public DataClassViewModel
{
//Define all relevant properties here.
...
public DataClassViewModel(DataClass model) //Constructor
{
//Initialize the view model from the model.
}
public DataClass GetModel()
{
//Depending on changes in the view model, model could be updated here.
}
public void UpdateData()
{
}
}
You can read more about view model's here:
Model-View-ViewModel (MVVM) Explained
How we do MVC – View models
What is ViewModel in MVC?
Although the articles point to MVC/MVVM UI architectures, view model is quite a general concept.
I've been trying to find a flexible way of exposing an object through a 'view'. I'm probably better off explaining by way of example.
I have an Entity Framework entity model, and a web service that can be used to query it. I am able to return the entity classes themselves, but this would include some fields I might not want to share - IDs, for examples, or *Reference properties from any associations in the entity model.
I figure what I need is a view of the data, but I don't particular want to write a view wrapper class for every return type. I'm hoping I'll be able to define an interface and somehow make use of that. For example:
interface IPersonView
{
string FirstName { get; }
string LastName { get; }
}
-
// (Web service method)
IPersonView GetPerson(int id)
{
var personEntity = [...];
return GetView<IPersonView>(personEntity);
}
However, in order to do something like this, I'd have to have my entities implement the view interfaces. I was hoping for a more flexible 'duck-typed' approach as there may be many views of an object, and I don't really to want to have to implement them all.
I've had some success building a dynamic type by reflecting the interface and copying fields and properties across, but I'm not able to cast this back to the interface type in order to get strong typing on the web service.
Just looking for some comments and advice, both would be welcome. Thanks.
You shouldn't ever really be passing entities directly out to a client, they should be used for persistance only. You should introduce DTOs/POCOs tailored to whatever data your API wants to return e.g.
public class PersonDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
// public API method
public PersonDto GetPersonApi(int id)
{
var personEntity = // pull entity from db
return new PersonDto()
{
FirstName = personEntity.FirstName,
LastName = personEntity.LastName
};
}
This keeps a clean separation between your persistence layer & public interface. You can use a tool like AutoMapper to do the legwork in terms of mapping the data across. Just setup a mapping once e.g. in your global asax:
protected void Application_Start()
{
Mapper.CreateMap<Person, PersonDto>();
}
...
// public API method
public PersonDto GetPersonApi(int id)
{
var personEntity = // pull entity from db
return Mapper.Map<Person, PersonDto>(personEntity);
}
I typically see this done with AutoMapper or a similar tool. It makes mapping between similar classes much simpler. You still have to create the Views (which in an MVC-context would be a Model), but the most tedious part (the mapping) is taken care of for you so long as you use the same field names.
As a side note, sharing IDs and other reference data will be necessary if you want to update the data, since you'll need to know the keys in order to know which record(s) to update.
In ASP.NET MVC, Where should one work with view models?
Should this be done strictly in the controller? Or would it be ok to say, return a view model from a repository method?
To my mind viewmodels are specific to whatever application is going to use them, whereas a repository would return a model common to all applications. So I'd say the view model should be created within the web site, from a common model returned from the repository, rather than tie the repository into knowing about how views are laid out.
Strictly speaking your repository should return domain objects
Repository: "Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects."
Fowler (PoEAA)
Viewmodels should be instantiated in your controller and passed to the strongly-typed view. Typically a ViewModel will contain multiple model types necessary to render your view. Here's a Quick Example:
Say you have two model objects Orders and Customer
You want to display Customer Details at the top of the page and a Grid of Orders in the Index view for that customer.
public class CustomerModel
{
//properties
}
public class OrderModel
{
//properties
}
public class CustomerVM
{
public CustomerModel customer { get; set; }
public IEnumerable<OrderModel> orders { get; set; }
}
//and in your controller
public class CustomerController : Controller
{
public ActionResult Index(int id)
{
CustomerVM vm = new CustomerVM();
vm.customer = CustomerRepository.GetCustomer(id);
vm.orders = OrdersRepository.GetOrdersForCustomer(id);
return View(vm);
}
}
repository should be a in between your domain and UI - the repository should know nothing about your UI layer - so you can get the best re-use and decoupling from it as possible.