Validation in data first approch - c#

I am implementing a project using mvc 4 and entity framework.
where i used data first approach. and i am implementing a partial class for my models for various business logic.
my question is how can i set validation rule on my properties. shown in below.
[Required]
public string FirstName { get; set; }
if i manually added this code "[Required]" on a property (entity framework generate models).
and then if i need to change model for database changes. then all my validation rule is gone
how can i over come this problem, without using code first approach.

As you've found out you should never edit the generated files since changes are lost when you regenerate them.
A better architecture than to use the entities as models for your views is to insert a separate View Model between the view and the entity. The view model should correspond closely to the needs of the view and often retrieves data from several underlying entities.
The attributes then goes on the view model properties instead of on the entities.
View models also remedies the risk of mass assignment vulnerabilities in your application, which are particularly dangerous if you are using lazy loading in your entities.

Another way around this (using CodeFirst) is to use a Fluent Validation. The CustomerValidator will always point at the regenerated Customer class (unless you change the Customer class name obviously)
using FluentValidation;
public class CustomerValidator : AbstractValidator<Customer> {
public CustomerValidator {
RuleFor(customer => customer.Surname).NotNull();
}
}

Related

Are classes generated by Entity Framework database classes or business classes? [duplicate]

This question already has answers here:
Should Entities in Domain Driven Design and Entity Framework be the same?
(4 answers)
Closed 5 years ago.
I have a three tier app with a class library as the Infrastructure Layer, which contains an Entity Framework data model (database first).
Entity Framework creates entities under the Model.tt folder. These classes are populated with data from the database.
In the past I would map the classes created by Entity Framework (in the data project) to classes in the Domain project e.g. Infrastructure.dbApplication was mapped to Domain.Application.
My reading is telling me that I should be using the classes contained in .tt as the domain classes i.e. add domain methods to the classes generated by Entity Framework. However, this would mean that the domain classes would be contained in the Infrastructure project, wouldn't it? Is is possible to relocate the classes generated by Entity framework to the Domain project? Am I missing something fundamental here?
I think in the true sense it is a Data Model - not a Domain Model. Although people talk about having the Entity Framework Model as a domain concept, I don't see how you can easily retro fit Value objects such as say amount which would be represented in the true domain sense as such:
public class CustomerTransaction
{
public int Id { get; set; }
public string TransactionNumber { get; set; }
public Amount Amount { get; set; }
}
public class Amount
{
public decimal Value { get; }
public Currency Currency { get; }
}
As opposed to a more incorrect data model approach:
public class CustomerTransaction
{
public int Id { get; set; }
public string TransactionNumber { get; set; }
public int CurrencyType { get; set; }
public decimal Amount { get; set; }
}
Yes, the example is anaemic, but only interested in properties for clarity sake - not behaviour. You will need to change visibility of properties, whether you need default constructor on the "business/data object" for starters.
So in the domain sense, Amount is a value object on a Customer Transaction - which I am assuming as an entity in the example.
So how would this translate to database mappings via Entity Framework. There might be away to hold the above in a single CustomerTransaction table as the flat structure in the data model, but my way would to be add an additional repository around it and map out to the data structures.
Udi Dahan has some good information on DDD and ORM in the true sense. I thought somewhere he talked about DDD and ORM having the Data Model instance as a private field in the domain object but I might be wrong.
Also, that data model suffers from Primitive Obsession (I think Fowler coined it in his Refactoring book - although it Is in his book) Jimmy Bogard talks about that here.
Check out Udi Dahan stuff.
You should move your model to a different project. That is good practice. I don't quite get it what you meant by "moving to to Domain project" Normally entity framework generated classes are used as a domain model. No need for creating "different" domain model from this. This model should be use only near to database operations, whereas web(window) application should use only DTO (Domain transfer objects)
I don't know if you use it or not - but this is a nice tool allowing for recreating model from the database :
https://marketplace.visualstudio.com/items?itemName=SimonHughes.EntityFrameworkReversePOCOGenerator
This allows to store model in classes (instead of EDMX) Someone refers to it as "code first" but there is a misunderstanding. One can use this tool to create model and still be on "database first" This is done simply to omit using EDMX as a model definition.
You can relocate the entity classes by creating a new item in your Domain project: DbContext EF 6.x Generator (not sure of the name and you might have to install a plugin to get this item in the list, also exists for EF 5.x).
Once you have created this new item, you have to edit it to set the path of your EDMX at the very begining of the file. In my project for example it is:
const string inputFile = #"..\..\DAL.Impl\GlobalSales\Mapping\GlobalSalesContext.edmx";
You will also need to edit the DbContext.tt file to add the right using on top of the generated class. At each change you've done on the EDMX, you also will have to right click the generator and click: "Run custom tool" to generate the new classes.
That being said, is it a good practice? As you can see that's what I have done in my project. As long as you do not have EF specific annotations or stuff like that in the generated entity classes, I would said that it is acceptable.
If you need to change your ORM, you can just keep the generated classes and remove all the EF stuff (.tt files, etc) and the rest of your application will work the same. But that's opinion based.

asp.net mvc model the same as (database mapped) object?

I have the following setup: fluent nhibernate + asp.net mvc 4.
I have a seperate project in VS where all my objects are stored, these objects are directly mapped to the database.
However, to display data from these objects in the views, I need 'models'.
Do I need to create new model objects, based on these database mapped objects, or can I just pass these database objects as a model to the view? (is this a good idea?)
Thanks!
In my opinion you should create additional ViewModel classes. If some changes are to be made to the data that get displayed, it's easier to just modify these models; your domain mappings will not be affected by some particular "rendering" circumstances.
Another advantage would be that you can decorate the properties with formating attributes, without enforcing these settings on future projects that depend on your domain.
For example, say you have the following Customer class in your base project:
public class Customer
{
public string Name { get; set; }
public string Address { get; set; }
}
You can add a [Required] attribute on the Name property to make it mandatory. If for a particular project you need to also make the Address property mandatory, you would decorate it with another [Required] attribute. If you directly use the domain model classes, you will enforce that the Address property would always be required, even though the project requirements would not state that. This can be further extended to different validation attributes and also additional data that you may want to sent to the view along with the model (such as composite fields).
This is largely a design decision that depends on the size of the project, etc. Without getting into too much detail, the short answer is yes, you can use your database objects/models directly in your Views.
Sometimes it may be desirable to create specific view models if you only want to show a subset of the fields, or do different validation than the database in your View. You can then can validate this view model in your controller and if everything is okay, map it to your nHibernate models.

Entity Framework - MVC - Converting data types requested from database in Model (POCO objects) into business objects used in the View

I am using MVC pattern and entity framework 4.1. I have three projects: Model (M) , View (V) and Controller (C).
M <-------- V --------> C
^ |
|_______________________|
View project references Controller and mode projects.
Controller project references model project.
and between Model and View there is another project, let's say project MV, with contains an interface and some converters (I will explain below).Model project references MV. Also view references MV as well. But MV is independent, it does not reference any project, neither Model nor view.
In the model I Have my POCO objects (Entities), those define the physical database design.
As I want to isolate model from view, that is, I do not want model depends on view, the models has its own entities and the view has its own as well.
for example in the View namespace I have below object:
public class EntityA : InterfaceMV
{
public string Property1 { get; set; }
public int Property2 { get; set; }
EntityB entityB; <--- refrences an entity in the same namespace
}
and in the Model namespace I have below object, that in fact it contains the same attributes:
public class EntityA : InterfaceMV
{
public string Property1 { get; set; }
public int Property2 { get; set; }
EntityB entityB; <-- foreign key to an entity in the same namespace
}
I do not have entities that are shared in Model and View so my problem is when from view I access directly to the model to retrieve some data using the context so from view I do:
using (DBContext context = new DBContext())
{
Namespace.Model.EntityA a = context.EntitiesA.Find(id);
}
as model and view uses different entities (despite they have the same attributes and the same name they are treated as different objects as they are beloging to different namespaces), I have to convert data from model object to view object. This conversion is done using a converter (interface) that I have in the interface (InterfaceMV) contained in project MV commented above. The InterfaceMV is as below:
public interface IDataTypeConverterEntityA
{
string Property1 {get; set;}
int Property2 {get; set; }
}
and InterfaceMV is implemented by EntityA in model and EntityA in View. So once I retrieve data from model from the view:
Namespace.Model.EntityA a = context.EntitiesA.Find(id);
I have to convert the 'a' object (which is of type Namespace.Model.EntityA) into the equivalent in the View:
EntityA aConverted = DataTypeConverterEntityA.Convert<Namespace.Model.EntityA, EntityA>(a);
the the converter is like below (it is inside the class DataTypeConverterEntityA):
public static Y Convert<T, Y>(T itemToConvert)
where T : new(), IDataTypeConverterEntityA
where Y : new(), IDataTypeConverterEntityA
{
return new Y
{
property1 = itemToConvert.property1,
property2 = itemToConvert.property2
};
}
Basicaly, I have my POCO entities that represent tables in my DB, and I have some business classes and I use the converter to move from one to the other.
The problems are the following:
1.- As project MV which contains the interfaceMV does not references neither the model nor the view, convert method can only convert scalar types but not for example other types such as EntityB property so once obtained converted object aConverted in the view:
// I retrieve the matching entity from the context
EntityA aConverted = DataTypeConverter.Convert<Namespace.Model.EntityA, EntityA>(a);
I have to do antoher request to database to obtain EntityB, then convert it and finally assign from the view to EntityA.entityB by doing:
// I retrieve the matching entity from the context
Namespace.Model.EntityA a = context.EntitiesA.Find(id);
EntityA aConverted = DataTypeConverterEntityA.Convert<Namespace.Model.EntityA, EntityA>(a);
// Inject values into the entity
Namespace.Model.EntityB b = context.EntitiesB.Find(id);
EntityB bConverted = DataTypeConverterEntityB.Convert<Namespace.Model.EntityB, EntityB>(b);
aConverted.entityB = bConverted;
2.- As you can see I must have a converter for each entity because from the view I cannot treat the object received from the database request as the view uses its own entities..... and obviously I have to implement the interface in each entity, that in model's entity and that in View's entity.
The cause of this is that I have isolated the model project completely, it is using its own entites and the view also is using its own.
Maybe keeping entities (EntityA, EntityB, ....) in only one place and sharing them between Model and View would solve this issue.... avoiding using data types converters.
so my question is: is there any better approach to avoid using data type converters each time? or do you think this architecture is good as it isolates Model from View? with this approach if you do changes it entities in View, the model it is not affected as it has its own entities. My problem is using data type converters each time....
Any ideas?
Instead of writing your own converter for each class take a look at AutoMapper. It will save you from a whole lot of coding.
Not sure if this is really a question for Stack Overflow (feels too much like "what's your opinion on..."), but since you took the time to type up such a long explanation, I will render my two cents:
I think you've over-complicated your design. There's an adage about "the complexity of the solution should not exceed the complexity of the problem," which it feels like you've done (hard to say without specific contextual knowledge of your problem). For what it's worth, the "pattern" I've found to be the best tradeoff between SoC and complexity is this:
Data project. Provides programmatic access to the data store
(database, XML, etc.).
Domain project. Provides implementation of business logic/rules. I
also define my DTOs here.
UI project. Assuming you're developing a tool for a user to use
directly, this project provides the website, console, or desktop
app, and is limited to basic validation (were required values
supplied, for instance).
If I need hashing or encryption routines, I've tended to place them in a fourth project, but they can also be lumped in with the domain project.
Given this design, the domain project references the data project, and the UI project references the domain project. The lion's share of the work happens in the domain project, with the data project normally just being a wrapper for the data store, and the UI project routes user requests to the appropriate domain logic.
HTH.

Should I refer to Entity Object class always as DAL or I can use its classes?

Let's say I have 'Customer' table in SQL DB and I'm using Entity Framework.
Now, for instance, in Controller or ViewModel I retrieve the customer by var customer = Page.Current.Customer when it's code is:
public class Page
{
...
// Customer is EntityObject that created by Entity Framework
public Customer Customer
{
get
{
return (new ContextEntity()).Customers.First();
}
}
}
My question:
Should I refer to Entity Object class(Customer) as DAL and create CustomerWrapper or I can use it in other code of my application?
I mean, is it correct that Page.Current.Customer will return Customer Entity or I should use Customer Entity as DAL and Page.Current.Customer should return custom Customer, some kind of CustomWrapper?
In one hand if will decided to change Customer table name to site_Customer(in SQL DB) I'll refresh the EntityModel and will only change the code in the Page class to
public class Page
{
...
// Customer is EntityObject that created by Entity Framework
public Customer Customer
{
get
{
return (new ContextEntity()).site_Customers.First();
}
}
}
But in the other hand I'll have Customer Entity + WrapperCustomer
What is better?
All class in an EDMX file are partial classes. This means that you can extend these classes by creating a new Class file.
For example...
public partial class Customer
{
// Here are the methods, properties, relationships created by EDMX Wizard.
}
In another area of your project, I usually put it in the same location as the EDMX, you can add a new Class file that has the same signature.
public partial class Customer
{
// Here are the methods, properties, etc. created by you.
}
When the project is compiled these two classes will become one class in the compiled code. Now, when you change your EDMX, yes it should map correctly, but this is not always the case as EF has be known to be very buggy (suppose to be fixed with EF 4.1 in MVC 3), you can simply change the class name to match whatever it is in the EDMX and "Voila!" you have transferred all custom added code for the class to the new entity object. This is essentially your "class wrapper".
That all depends on the level of abstraction you want to use in your application and needs of presentation layer. Both approaches are possible.
Your code is probably already tightly coupled to Entity Framework (EntityObject is EF type) and it is also not very well testable (Page.Current is probably static) so discussion about some more advanced architecture approaches and separation of concerns is not needed.
Few observations from your code:
Context is Disposable!!!
Renaming anything in your database should not modify your class names. That is the responsibility of EF mapping (EDMX) to correctly map entities to new database names.
If you want to use WCF, then you will probably need to create clear POCOs to avoid a lot of issues.
If you want your controllers/viewmodels/pages/whatever to be unit testable, then you will need to abstract your EntityContext in repository interfaces+classes (see repository pattern).
If you just want to make a quick and simple non-testable application, then you don't need to bother about it. Don't forget to dispose the data context at the end of each request.

Can I add MVC 2 DataAnnotation attributes to existing properties?

I'm using a generated class as a model, and I wish to add DataAnnotation attributes to some of its properties. As it's a generated code, I don't want to add the annotations directly. Is there another way to attach them to a property?
I'd considered making the model an interface, and using a partial class to get the generated class to subscribe to it. Is there a less elaborate solution, assuming that would even work?
Yes there is. You have to create metadata class that will have the same properties that your original model, and connect it to your model with MetadataType attribute:
[MetadataType(typeof(MyModelMetadata))]
public partial class OriginalMyModel
{
}
public class MyModelMetadata
{
[Required]
public string MyProperty;
// ...
}
In the example ebove OriginalModel is your proper model class, and MyModelMetadata is a class used only for annotating properties. MyModelMetadata should have the same properties that your model has.
You can use the MetadataType attribute on your class:
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute.aspx
In practice, I've seen the metadata get out of sync with a generated model pretty frequently, though, which can lead to some headaches. You may want to look into an alternate validation mechanism instead of data annotations.
I've been using Fluent Validation, which is very easy to pick up and start using. There is even a Fluent Validation to xVal integration piece in Fluent Validation 2.0 (still in beta) that you can bring into your project for client-side validation.
Fluent Validation allows you to define your validation in a separate class. All you would need to do is add an attribute to your generated class telling it what validator to use, which could be accomplished through partial classes.
Alternatively, you could create view-specific models that are mapped to from your domain model that contain your data annotations. In that case, simplify the back-and-forth mapping using something like AutoMapper. Then, if your domain model changes, you get compile-time errors versus the metadata approach.

Categories