Showing posts with label ObjectContext. Show all posts
Showing posts with label ObjectContext. Show all posts

Tuesday, June 3, 2014

Step By Step How to create a Generic Data Repository in ASP.NET MVC 4

         By Carmel Schvartzman

In this tutorial we'll learn how to create a Generic Data Repository in ASP.NET MVC 4. This MVC C# code example can be downloaded from the following GitHub repository:
https://github.com/CarmelSoftware/Generic-Data-Repository-for-ASP.NET-MVC
A Wiki page is here:
https://github.com/CarmelSoftware/Generic-Data-Repository-for-ASP.NET-MVC/wiki
A Data Repository is a class designed to implement the Repository Pattern. This software pattern was designed in order to access, cache in memory and persist in the database the application data.  Thus the repository will support all CRUD operations (Create Retrieve Update Delete) enhancing a clear separation between data domain and database.
There exist Repository implementations with the use of data caching. The caching only stands to avoid unnecessary round trips to the SQL server. But when scalability of the sites is on the stage, may be we don't want to choke our web server's memory. Then, caching is not only redundant, but also dangerous as a waste of the web server resources.
In this tutorial we'll add GENERIC Repository functionality (no caching) to a new ASP.NET MVC 4 app.
That means, our Repository will offer all CRUD functionality, using the same GENERIC methods for all classes.
In successive tutorials, we'll use this Generic Data Repository to build MVC Applications as the following :



Let's say we have an MVC internet application with an Entity Data Model mapped to an SQL server database. This EDM maps just two entities: Blog and Comment:
Generic Data Repository in ASP.NET MVC 4

We'll develop a GENERIC Data Repository which will support ALL model entities in our application.
First, create a new class in the Model folder, name it "Repository", and type the following EDM context instantiation:

Data Repository in ASP.NET MVC 4

 public class DataRepository : IDisposable
    {
        #region Context
        private BlogEntities _Context;
        public BlogEntities Context
        {
            get
            {
                if (_Context == null)
                {
                    _Context = new BlogEntities();
                }
                return _Context;
            }

        }
        #endregion
Next, create the SAVE method, as follows:
Generic Repository in ASP.NET MVC 4

 public bool Save(object target, int RecordsNumber)
        {
            try
            {
                return Context.SaveChanges() == RecordsNumber;
            }
            catch (OptimisticConcurrencyException)
            {
                ObjectContext ctx = ((IObjectContextAdapter)Context).ObjectContext;
                ctx.Refresh(RefreshMode.ClientWins, target);
                return Context.SaveChanges() == RecordsNumber;
            }
        }

        public void Dispose()
        {
            if (Context != null)
            {
                Context.Dispose();
                GC.Collect();
            }
        }
As you see, we have a response in case of a concurrency exception. Optimistic Concurrency Exception means, we are optimistic in supposing that the current record being updated by us, is not being changed by anybody else. But, if at the moment we SAVE the record, the Entity Framework realize it has been changed in the meantime by somebody else, it will not allow us to save, but will throw an OptimisticConcurrencyException instead. What we do here, is REFRESHING the entity (getting the updated record) , state that CLIENTWINS over the data store (meaning that OUR changes override the record from database), and then SAVE it again.
Notice that we CAST the DbContext in an ObjectContext, in order to REFRESH the data.

Now let's code the complete C.R.U.D. (Create Retrieve Update Delete) operations, in a generic way:
Generic Data Repository

public void Create<T>(T entity) where T : class
        {
            Context.Set<T>().Add(entity);
        }
We typed a generic Create method using the generic Set<T>( ) method from the DbContext.
Now, Retrieve will support 3 cases :
   1) retrieve ALL records : if both parameters ID and PRED are empty : it's sensible, isn't it?
   2) retrieve just ONE record : if ID contains a value
   3) retrieve SELECTED records according to a PREDICATE : if the PRED parameter is set :
Data Repository ASP.NET MVC 4

public List<T> Retrieve<T>(int? Id, Func<T, bool> pred) where T : class
        {
            List<T> list = new List<T>();
            if (Id.HasValue)
            {
                list.Add(Context.Set<T>().Find(Id.Value));
            }
            else if (pred != null)
            {
                list = Context.Set<T>().Where(pred).ToList();
            }
            else list = Context.Set<T>().ToList();
            return list;
        }
Now for the UPDATE method, just get the local entry, and set its state to "modified" :

public void Update<T>(T entity) where T : class
        {
            var e = Context.Entry<T>(entity);
            e.State = EntityState.Modified;
        }
Finally, DELETE just removes the entity : 
Repository ASP.NET MVC 4
public void Delete<T>(T entity) where T : class
        {
            Context.Set<T>().Remove(entity);
        }
That's all the GENERIC Repository.

How to use it? Example of using it on a Controller:
Get ALL records : 
Generic Data Repository

Get a LIST of SOME records : 

Generic Data Repository in MVC 4

Get just ONE record : 
 CREATE a new record : 


UPDATE a record : 


DELETE a record :

 This is the complete Generic Data Repository code for you:
public class DataRepository : IDisposable
    {
        #region Context
        private BlogEntities _Context;
        public BlogEntities Context
        {
            get
            {
                if (_Context == null)
                {
                    _Context = new BlogEntities();
                }
                return _Context;
            }

        }
        #endregion
        ///////// GENERIC C R U D METHODS :
        public void Create<T>(T entity) where T : class
        {
            Context.Set<T>().Add(entity);
        }
        public List<T> Retrieve<T>(int? Id, Func<T, bool> pred) where T : class
        {
            List<T> list = new List<T>();
            if (Id.HasValue)
            {
                list.Add(Context.Set<T>().Find(Id.Value));
            }
            else if (pred != null)
            {
                list = Context.Set<T>().Where(pred).ToList();
            }
            else list = Context.Set<T>().ToList();
            return list;
        }
        public void Update<T>(T entity) where T : class
        {
            var e = Context.Entry<T>(entity);
            e.State = EntityState.Modified;
        }
        public void Delete<T>(T entity) where T : class
        {
            Context.Set<T>().Remove(entity);
        }
        public bool Save(object target, int RecordsNumber)
        {
            try
            {
                return Context.SaveChanges() == RecordsNumber;
            }
            catch (OptimisticConcurrencyException)
            {
                ObjectContext ctx = ((IObjectContextAdapter)Context).ObjectContext;
                ctx.Refresh(RefreshMode.ClientWins, target);
                return Context.SaveChanges() == RecordsNumber;
            }
        }

        public void Dispose()
        {
            if (Context != null)
            {
                Context.Dispose();
                GC.Collect();
            }
        }
    }



That's All !!!! 
In this tutorial we've learned how to create a  Generic Data Repository in ASP.NET MVC 4.  

Happy programming.....


כתב: כרמל שוורצמן

Thursday, January 2, 2014

Step By Step How to add Bussiness Logic Validation to an ASP.NET MVC 4 Application

         By Carmel Schvartzman

In this tutorial we'll learn how  to add Bussiness Logic Validation to an ASP.NET MVC4 application


Concerning the Model in a MVC application, there are two kinds of errors that can happen: data type errors or bussiness logic errors. While the data type errors are usually handled using Data Annotations, the later are usually handled in special classes which extend the DAL of the application. Remember that when you use the Entity Framework as the DAL (Data Access Layer) of your MVC, every time you update the conceptual data model to reflect changes made to the data store, the Model classes are regenerates by a tool, meaning that everything that's in it is erased and rewriten. Therefore the Bussiness Rules are usually coded in partial classes which extend the Model classes.

The Bussiness Logic comprehends both Application Logic (the logic of the interaction between the user and the specific application we developed - web win etc) and Data Store Logic (the logic concerning exclusively the data, no matter which kind of application you have).

The Application Logic will usually  be on the Controllers, because it concerns to the specific application, an MVC app in our case.

The Bussiness Data Logic MUST BE located in the Model, in a separate BLL (Bussiness Logic Layer) folder, and usually is coded in partial classes which extend the DAL (Data Access Layer) created for example by the Entity Framework.

In this tutorial we'll create a BLL (Bussiness Logic Layer) coding partial classes which extend the DAL (Data Access Layer). Let's say we have an MVC 4 app connected to an SQL SERVER database with the following tables on it:



We'll state that the user can save temporarily a comment with a Title but no text, or with a Text but no Title. But it is not allowed to save a comment without text and without title. This is a Bussiness Data Logic rule, which we'll code in an extension of the corresponding Comments Entity.

Focus the Model folder and create a new class on it. Inside, code the extension of the Comment class which we want to enable to apply our Bussiness rule:


Add a MetaData class named CommentMetaData, as we did in a previous tutorial , in order to enable Data Type Validation:


Next, do the Comment class to implement the IValidatableObject:


This way will allow us to code a Validate() method to perform the necessary bussiness logic on our entity, returning an IEnumerable collection holding all input errors.


Add the Validate method with its returned ValidationResult collection:



Finally, code the required if clause stating that we wont persist an user comment only in case of the lack of both Title and Text: 



Now let's make use of the IValidatableObject: provided that you already have a form where the user will type her/his comment. If you don't, referer to this tutorial . Go to the Home Controller and find the method which handles POST requests:


There, add an if clause using our Validate() method, which IEnumerable results count will be 0 only in case of valid input:



Open the Comment's form and save two comments, the first having only a Title but no text, the second having Text but no Title:




Now check the database to see the persisted records:



Then try to persist a Comment with no Title nor Text:



The comment has not been saved, because our extended Comment entity didn't allow that.
To see it from inside, set a breakpoint in the Validate() method, and try to save an empty Comment again. You'll see that the runtime enters the if clause , avoiding saving the record:




That's all!! 
Happy programming.....


כתב: כרמל שוורצמן

Wednesday, January 1, 2014

Step By Step How to add Model Data Validation (Database First) to an ASP.NET MVC 4 application

         By Carmel Schvartzman

In this tutorial we'll learn how  to add Model Data Validation to an ASP.NET MVC4 application, while using the Database First approach of the Entity Framework


Concerning the Model in a MVC application, there are two kinds of errors that can happen: data type errors and bussiness logic errors. The later are usually handled in special classes which extend the DAL of the application. Remember that when you use the Entity Framework as the DAL (Data Access Layer) of your MVC, every time you update the conceptual data model to reflect changes made to the data store, the Model classes are regenerates by a tool, meaning that everything that's in it is erased and rewriten. Therefore the Bussiness Rules are coded in partial classes which extends the Model classes.

For that reason, decorating entities's fields with Data Annotations will not work while using the Database First approach of the Entity Framework. Every time you refresh the conceptual Model, your annotations will be overriden. In this tutorial we'll use Data Annotations with the  the Database First approach.

The MVC Data Model created automatically by the Entity Framework captures the data type errors caused by incompatibility between data types, and throws exceptions notificating the user about the problems.

This kind of errors can be easily handled using Data Annotations, by decorating the entity's fields with attributes. That way, custom validation rules will be enforced not only while persisting data to the store, but whenever MODEL-BINDING OPERATIONS are performed by MVC.
The  following validator attributes are supported:
   Range – checks if the value of a property is between a specified range.
   ReqularExpression – checks whether the value matches a specified regular expression.
   Required – sets a property as required.
   StringLength –  checks whether a maximum length for a string property is legal.
   
There is also the option of inheriting from the base class "Validation" in order to enforce custom validation.

Let's say we have an entity named "Comment" mapped to the database table Comment with the following properties:

Notice that the "Title" column holds strings up to 100 characters. We'll try to enter comments with a title longer than that, to check the Data Validation.
In order to check it, create a new test class in the Model folder:


This static class contain a method which just creates a new Comment, add it to the context, and tries to persist it to the database. The Data Model Validation of the Entity Framework will automatically refuse to do that and will throw an DbEntityValidationException:



The exception, however, doesn't reveal us which field caused it:


We' want to catch this exception in a friendly user way and inform what is causing the problem.
To do that, we'll create a MetaData class with the necessary Data Annotations, and extend the partial class Comment created by the Entity Framework to link it to the metadata file.

Therefore we'll extend the Comments class taking care to copy exactly the name of the class:



Copy this to a new file named CommentMetaData.cs, containing the following two classes:



First think we must do is adding the System.ComponentModel.DataAnnotations namespace to the entity class we want to validate:



Add an attribute setting the MetaData Class for the Comment class:


Now copy the properties you want to add validation to, from the original class Comment:


And paste them, adding the necessary validation attributes, specifying the maximal lenght of the Title:



Next, we'll add a View to create Comments, to see how it works:



Add the corresponding Action to the Home Controller:


And the ActionLink to the Menu in the _Layout.cshtml file:


Finally, add the Action to cope with Comments creation, on the Home Controller:



Rebuild the MVC project (F6) and browse to the Comments Page:


In it, type some valid data to check if it's saved correctly:


Check the data in the database. Yes, it was persisted:



Now type some invalid input, and try to save it:


The Message error that you wrote on the MetaData class is presented to the User to inform her/him that the length of the Title was illegal, and the Comment is not saved:




That's all!! 
Happy programming.....


כתב: כרמל שוורצמן