How to use AutoMapper properly?

I will not talk about things that are easily accessible by googling. Instead, I will try to explain the suggested way of using AutoMapper in your .NET projects, with examples when necessary.

Entity Framework

The most widely used ORM technology in .NET world is obviously Entity Framework, so I will focus on it but suggestions here apply to other ORM technologies too.

You have POCO objects that are mapped to data entities. One usually requires to do CRUD operations on these entities. Intuitively, one would use already existing POCO objects to accomplish the job, however it might not be suitable for all cases. In an MVC architecture, CRUD operations are handled by controllers and in an MVVM architecture they are handled by ViewModels. However, people have started to adapt an M-V-VM-C architecture to go further with the separation of concerns philosophy:

  • Model: POCOs, a Repository, and definition of mappings between POCOs and actual data entities.
  • View: Plain old views to display existing data without further modifications to them.
  • ViewModel: Similar to Model, this layer has POCOs and definition of mappings between Model POCOs and ViewModel POCOs. This is where AutoMapper will play its role.
  • Controller: CRUD operations and all business logic remains here and only here unless you split your business logic among different controllish layers.

So with an M-V-VM-C architecture in hand, it is clearer where AutoMapper definitions should be placed. My favorite method is by putting them into relevant ViewModel’s static constructor:

Model POCO (I have explicitly defined ManyToMany middle table):

namespace yourproject.Models
{
public class Student
  {
    public string ID { get; set; }
    public string Name { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int SchoolID { get; set; }
    
    public virtual School School { get; set; }
    public virtual ICollection<StudentCourse> StudentCourses { get; set; }
  }

  public class School
  {
    // PK is School
    public string Name { get; set; }
    
    public virtual ICollection<Student> Students { get; set; }
  }
  
  // Many to many table between Student and Course
  public class StudentCourse { get; set; }
  {
    public int StudentID { get; set; }
    public int CourseName { get; set; }
    
    public virtual Student Student { get; set; }
    public virtual Course Course { get; set; }
  }
  
  public class Course
  {
    public int ID { get; set; }
    public string Name { get; set; }
    
    public virtual ICollection<StudentCourse> StudentCourses;
  }
}

ViewModel POCO:

namespace yourproject.ViewModels
{
  public class StudentVM
  {
    static StudentVM
    {
      // All properties are automagically mapped by AutoMapper, except CoursesTaken.
      // I'm not sure if AutoMapper expects getter-only property to be ignored, try it out.
      
      
      Mapper.CreateMap<Student, StudentVM>()
        .ForMember(dest => dest.FullName, opt => opt.Ignore())
        .ForMember(dest => dest.Age, opt => opt.Ignore())
        .ForMember(
          dest => dest.CoursesTaken,
          opt => opt.MapFrom(
            src => 
              src.StudentCourses.Select(src => src.Course.Name).ToList()));
    }
    
    public string Name { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int Age { get; set; }
    public string SchoolName { get; set; }
    public List<string> CoursesTaken { get; set; }
    
    public string FullName {
      get {
        return Name + " " + LastName;
      }
    }
    
    // Calculation of age is not accurate, check http://stackoverflow.com/questions/4127363/date-difference-in-years-c-sharp
    public int Age {
      get {
        DateTime.Now.Subtract(DateOfBirth).Days / 365;
      }
    }
  }
}

One frequent question about Model-ViewModel mapping in Entity Framework is, should one do the reverse mapping, i.e. ViewModels to Models? Jimmy Bogard discusses it here.

What is my opinion on it? Well, he is correct about collections and they mostly require special treatment before persisting them. My suggestion is to create a mapping from ViewModels to Models, ignoring all navigation properties and handling them in the Controller layer. For the example above, reverse mapping would look like the following:

// The rest will be automapped.
Mapper.CreateMap<StudentVM, Student>()
  .ForMember(dest => dest.ID, opt => opt.Ignore)
  .ForMember(dest => dest.SchoolID, opt => opt.Ignore)
  .ForMember(dest => dest.School, opt => opt.Ignore)
  .ForMember(dest => dest.StudentCourses, opt => opt.Ignore);

Some may have trouble understanding why I did not map the non-collection type navigation property `School`. Well, in the ViewModel, we have the SchoolName property and mapping it requires fetching the School with that name from the repository and assigning it to either SchoolID or School property of the actual model. We do not want to do that in the ViewModels layer.

WCF

WCF has been around the .NET scene for a while now and it provides an easy way to have a service that other applications can communicate with. It broadcasts a contract so that other applications know how to communicate with it. Consider the following:

namespace yourproject.SchoolService
{
  [ServiceContract]
  public interface ISchoolService
  {
    // DC stands for DataContract
    [OperationContract]
    List<StudentDC> GetStudents(string schoolName);
  }

  [DataContract]
  public class StudentDC
  {
    [DataMember]
    public string ID { get; set; }
    
    [DataMember]
    public string Name { get; set; }
    
    [DataMember]
    public string LastName { get; set; }
    
    [DataMember]
    public DateTime DateOfBirth { get; set; }
    
    [DataMember]
    public int SchoolID { get; set; }
  }
}

Why do we need AutoMapper here? Because there needs to be a mapping between Student and StudentDC. I cannot suggest you the location where mappings should be defined because I am not proficient with the service oriented approach. However, common sense suggests that it would happen at the place where you merge your application with the ISchoolService. And again, a static constructor makes sense.

Book review

anilanar:

I guess this is the second book on Automapper, that I have seen, other than this. I will soon talk about AutoMapper in depth.

Originally posted on Prashant Brall's Blog:

I was recently contacted by packet publication to review the book Instant Automapper by Taswar Bhatti and I am happy to say that finally the book is published. It was real pleasure to be part of this publication and good to see the impact of so many open source project on .NET framework :).

Here are some of the topics the book covers.

  • Learn to use Automapper with practical examples
  • Find out why Automapper is so useful when building applications
  • Discover how to leverage Automapper to solve most of your common object-to-object mapping needs
  • Create your own Custom Resolvers for mapping
  • Configure and test the mapping


Instant AutoMapper book by Taswar Bhatti reviewed by Prashant Brall

View original

Prevent Property From Updating Upon SaveChanges(), Eternally!

If you have read my previous post, you may have become aware that it is possible to modify the behavior of SaveChanges() upon your needs.

There is a frequent question being asked on stackoverflow: How to exclude a property from updating upon SaveChanges()? That is an easy question to answer: this, this and this will probably meet your needs; so check them before you continue.

The question that I am going to answer (as obvious from the title) is how to develop an attribute [NeverUpdate] to prevent Entity Framework updating a property.

public class Student
{
    [NeverUpdate]
    public string Name { get; set; }
    public string Address { get; set; }
    …
}

So for the model class `Student`, `Name` property won’t be updated even if it is changed, a behavior you may need in certain situations to prevent code repetition. Whatever your motivation is, here is the solution:

The [NeverUpdate] attribute:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class NeverUpdateAttribute : System.Attribute { }

SavingChanges: (check this post to see how to handle SavingChanges event)

void ObjectContext_SavingChanges(object sender, System.Data.Objects.SavingChangesEventArgs e)
{
    ObjectContext context = sender as ObjectContext;
    if(context != null)
    {
        foreach(ObjectStateEntry entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
        {
            var type = typeof(entry.Entity);
            var properties = type.GetProperties();
            foreach( var property in properties )
            {
                var attributes = property.GetCustomAttributes(typeof(NeverUpdateAttribute), false);
                if(property.GetCustomAttributes.Any(attr => attr.GetType() == typeof(NeverUpdateAttribute))
                    entry.RejectPropertyChanges(property.Name);
            }
        }
    }
}

It is that easy. This approach can be extended or modified easily to accomplish whatever you need. Have fun!

Execute Code Before Save and After Fetch in Entity Framework

Thanks to Sam Changtum for the insight in his post.

This tutorial addresses two issues:

  • If you want to execute some code before your DbContext is saved
  • If you want to execute some code after your DbContext fetches some data and materializes them into your Model POCO objects
  • If you want to throw an exception depending on some constraints when SaveChanges() is called.

DbContext implements the interface IObjectContextAdapter and it returns an ObjectContext instance. ObjectContext has two events that are related to our problem: ObjectMaterialized and SavingChanges. You can attach methods to those events to handle them.

Clarification:
When you call a query such as the following, ObjectMaterialized event is raised for each student, e.g. If the result of your query has 10 students, the event will be raised 10 times. It is the same for SavingChanges.

YourDbContext.Students.Where(s => s.Courses.Any(c => c.Name == "Math")).ToList()

So this is how you modify YourDbContext class:

public class YourDbContext : DbContext
{
	public YourDbContext()
	{
		((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized;
		((IObjectContextAdapter)this).ObjectContext.SavingChanges += ObjectContext_SavingChanges;
	}

    static void ObjectContext_ObjectMaterialized(object sender, System.Data.Objects.ObjectMaterializedEventArgs e)
    {
        if (e.Entity == null)
            return;
        if (e.Entity.GetType() == typeof(Student))
        {
            Student student = e.Entity as Student;
            // There is no problem in using Navigation Properties here
			// If they haven't been materialized yet, it will be done here, but only once.
			// Don't worry, there will be no stack overflow.

			Teacher teacher = student.Teacher;
			Course firstCourse = student.Courses.First();

			// Do whatever you want here with your entities.
        }
    }

    static void ObjectContext_SavingChanges(object sender, System.Data.Objects.SavingChangesEventArgs e)
	{
		ObjectContext context = sender as ObjectContext;
		if(context != null)
		{
			// You can use other EntityState constants here
			foreach(ObjectStateEntry entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
			{
				// You can handle multiple Entity Types here. I use Student as an example for the sake of simplicity
				if(entry.Entity.GetType() == typeof(Student))
				{
					Student student = entry.Entity as Student;
					// Do whatever you want with your entities.
					// You can throw an exception here if you want to
					// prevent SaveChanges().
					if(student.Teacher == null)
						throw Exception("Something went wrong.");
				}	 
			}
		}
	}
}

Performance Implications

Let’s assume that there is a function called MyFunction(Student s). The following snippet is equivalent to calling MyFunction for each student entity object in ObjectMaterialized event handler, in terms of performance. The same goes for SavingChanges event handler if you move the foreach loop before a call to SaveChanges. So the performance implications depend on what’s inside MyFunction. Thus, when you use navigation properties, be careful. EF will fetch related entity objects if they aren’t already fetched. If you’re not confident in your code, check some resources on Lazy Loading/EF.


DbContext context = new DbContext();
List<Student> students = context.Students.ToList();

foreach(var student : students)
{
	MyFunction(student);
}

Upload Youtube Videos For Single Account (ASP.NET MVC)

This post does not intend to explain how to let your clients/users upload videos to their own Youtube accounts.

Note: This method requires you to store the video file in your filesystem before you upload it to Youtube.

I am working on a ASP.NET MVC4 web application project. I wanted to let my clients upload videos but I didn’t want to hassle with many issues that may arise while processing video files. I am specifically talking about codecs, conversions, resizing etc.

Thus I have decided to use Youtube API to upload those to my Youtube Channel and display them using the official Youtube player. So I have started googling and the first page I landed on was Getting Started with the Youtube Data API.

  • First Step: Registering your application and setting Youtube API on from Services (in Google API Console) is straightforward.
  • Second Step: Now this is where it gets confusing. You need an OAuth account to authorize your account with Google services. Creating an OAuth account simply means generating a ClientID. There are 3 different ClientIDs that you can generate:
    • Web application: I think this is for those who want to let their users access Google services from their own accounts.
    • Service account: This one is interesting and I thought I would need a Service account until I have learnt that a service account cannot have a Youtube Channel attached, thus it is impossible to use it for uploading videos. Basically, it lets you use a single unordinary account to access Google services.
    • Installed application:We are going to use this. It is targeted mostly for desktop and mobile applications to let users access Google services from their own accounts. This is the same as the web application. It may seem to you that it will not work for us but you are wrong.
  • Third Step: Follow this guide: Youtube API single-user scenario with OAuth (uploading videos). At this point, you got 3 pieces of information: ClientID, ClientSecret and RefreshToken. You can find ClientID and ClientSecret in your Google API Console but you need to keep RefreshToken safe. If you are a Windows user and you do not have Curl, download the Win32 or Win64 Generic SSL version.
  • Fourth Step: You need to prepare your development environment. There is a Google Apis package in NuGET but do not try that one, it may mess your references up and may cause creepy warnings in your project.
    • Download Youtube Data API Youtube Data API.
    • Add all DLL files in Lib folder (References -> Add Reference -> Browse).
    • Extract the zip file google-youtube-v3-***-csharp-*****-bin.zip and add Google.Apis.Youtube.v3.dll to your project as a reference.
  • Fifth Step: Read this if you wish to upload your video in a background thread/task.
  • Last Step: Coding. The following code snippet is pretty straightforward. Some of the required imports (using clauses) might be missing. If you have any questions, drop a comment.
...
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Youtube.v3;
using Google.Apis.Services;
using Google.Apis.Youtube;
using Google.Apis.Youtube.v3.Data;
using Google.Apis.Util;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Upload;

namespace Helicoder.Tutorials.YoutubeAPI
{
    public class YoutubeUploaderService
    {
        private static string CLIENT_ID = "Your ClientID";
        private static string CLIENT_SECRET = "Your ClientSecret";
        private static string REFRESH_TOKEN = "Your RefreshToken";

        private YouTubeService youtube;
        private IAuthorizationState refreshToken;

        public YoutubeUploaderService()
        {
            youtube = BuildService();
            refreshToken = new AuthorizationState()
            {
                RefreshToken = REFRESH_TOKEN
            };
        }

        public void UploadExampleVideo()
        {
            Video video = new Video();
            video.Snippet = new VideoSnippet();
            video.Snippet.Title = "SomeTitle";
            video.Snippet.Description = "SomeDescription";
            video.Snippet.Tags = new string[] {"tag1", "tag2"};
            video.Snippet.CategoryId = "22";  // You need to investigate Youtube API more to learn about category IDs
            video.Status = new VideoStatus();
            video.Status.PrivacyStatus = "private";

            FileStream fileStream = new FileStream("PathToYourVideoFile", FileMode.Open);
            VideosResource.InsertMediaUpload insertRequest = youtube.Videos.Insert(video, "snippet, status", fileStream, "video/*");
            insertRequest.ProgressChanged += insertRequest_ProgressChanged;
            insertRequest.ResponseReceived += insertRequest_ResponseReceived;
            
            insertRequest.Upload();
        }

        void insertRequest_ResponseReceived(Google.Apis.Youtube.v3.Data.Video obj)
        {
              // obj.ID gives you the ID of the Youtube video.
              // you can access the video from
              // http://www.youtube.com/watch?v={obj.ID}
        }

        void insertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress obj)
        {
            // You can handle several status messages here.
            switch (obj.Status)
            {
                case UploadStatus.Failed:
                    break;
                case UploadStatus.Completed:
                    break;
                default:
                    break;
            }
        }

        private YouTubeService BuildService() {
            var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description)
            {
                ClientIdentifier = CLIENT_ID,
                ClientSecret = CLIENT_SECRET
            };

            var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);

            YouTubeService service = new YouTubeService((new BaseClientService.Initializer()
                {
                    Authenticator = auth
                }));

            service.HttpClient.Timeout = TimeSpan.FromSeconds(360); // Choose a timeout to your liking
            return service;
        }

        private IAuthorizationState GetAuthorization(NativeApplicationClient client)
        {
            client.RefreshToken(refreshToken);
            return refreshToken;
        }
    }
}

MYSQL Trigger – Syntax Error: Unexpected END_OF_INPUT

If you are having this syntax error in MySql Workbench, then you may find the answer here.

The problem is with the delimiter. When you put a semicolon anywhere inside the trigger, mysql thinks that query for the trigger ends there. That prevents us from using semicolons in triggers, which is kind of limiting.

To overcome this limit, you need to have the following statement before your query (You are setting $$ as the new delimiter in your query).

DELIMITER $$

Here is an example:


DELIMITER $$

CREATE TRIGGER `expenseapp`.`check_application_approver_on_insert`
BEFORE INSERT ON `expenseapp`.`application`
FOR EACH ROW
begin
 SET NEW.user = null;
 SET NEW.count = 5;
end$$

Follow

Get every new post delivered to your Inbox.

Join 40 other followers