Implement Repository pattern with Entity Framework and C#

In the WebAPIConfig.cs file, register the repository with the Unity Container. This code file defines the delegate where you should put your Web API configuration code. Install the Unity Nuget package in your Project.

var container = new Unity.UnityContainer();

// this will register all Repositories that implement Repository<>. 
// because of the generics, you have to use the concrete type not the interface for injection
container.RegisterType(typeof(IRepository<>), typeof(Repository<>), new HierarchicalLifetimeManager());

Define the Repository interface:

public interface IRepository
{
bool Exists(int id);
IQueryable GetAll();
TEntity Get(int id);
}

Create the Abstract class for the Repository. The LogManager is for the log4net implementation for logging.

public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
	protected Models.DBEntities db = new Models.DBEntities();

	private DbContextTransaction Transaction { get; set; }

	protected static ILog log;


	public abstract TEntity Get(int id);
	public abstract IQueryable<TEntity> GetAll();

	public Repository<TEntity> BeginTransaction()
	{
		Transaction = db.Database.BeginTransaction();
		return this;
	}

	public abstract bool Exists(int id);


	// select specific columns into a DTO using specified selector
	//

	public abstract TResult Get<TResult>(int id, Expression<Func<TEntity, TResult>> selector);

	public abstract List<TResult> GetAll<TResult>(Expression<Func<TEntity, TResult>> selector);

	public Repository()
	{
		// setup the logger from the instance so we can get the derived type
		log = LogManager.GetLogger(this.GetType()); // should log as the derived type

		db.Configuration.LazyLoadingEnabled = false;

		setDBLogging();
	}

	public void logdb(string msg)
	{
		if (ConfigurationManager.AppSettings["LogDB"] == "true")
		{
			try
			{
				log.Debug(msg.Replace("\r\n", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty));
			}
			catch (Exception ex)
			{
				log.Error("failed logging DB activity", ex);
			}
		}
	}

	public void setDBLogging()
	{
		if (ConfigurationManager.AppSettings["LogDB"] == "true")
		{
			try
			{
				db.Database.Log = msg => logdb(msg);
			}
			catch (Exception ex)
			{
				log.Error("failed setting up DB logging", ex);
			}
		}
	}

}

Example Users Respository with a transaction:

using DBMODELS = ApiPersistence.Models;
public class UsersRepository : Repository<DBMODELS.user>
{
	public override bool Exists(int id)
	{
		throw new System.NotImplementedException();
	}

	public override DBMODELS.user Get(int id)
	{
		try
		{
			IQueryable<DBMODELS.user> query = from user in db.users
											  where user.id == id
											  select user;
			var userObj = query.FirstOrDefault();


			return userObj;
		}
		catch (Exception ex)
		{
			throw ex;
		}
	}

	public override IQueryable<DBMODELS.user> GetAll()
	{
		throw new NotImplementedException();
	}
	
	public UserDTO CreateUser(){
		//Example transaction:
		using (var transaction = db.Database.BeginTransaction())
		{
			try
			{
				///code for creating user goes here...
				db.SaveChanges();

				transaction.Commit();
			}
			catch (Exception ex)
			{
				transaction.Rollback();
				log.Error("caught exception", ex);
				throw new RepositoryException("CreateMethod()", "MyRepository CreateMethod() failed", ex);
			}
		}
	}
}

Select query for many-many relationship using linq C#

Select the data between tables with many-many relationship using linq query with Entity Framework and C# as shown in the code below:

db.roles.Where(x => x.resource_id == moduleid && x.resource_type == "MyModule" && x.name == "member").SelectMany(x => x.users.Select(u=>u.id)).First();

User and Role entities in the above example have many-many relationship using a join table in the database. The above example selects the User Id with member role.

Add remove data many-many relationship Entity Framework C#

Consider the example of a Users of an application having many roles like member, admin etc. The relationship in this case is many-many. The two entities in this case are Users and Roles. The many-many relationship is handled by a join table in the database say users_roles. If you import this join table in Entity Framework, it is automatically converted into a many-many association where the Users entity holds ICollection property of Roles entity and vice-versa.

public class User{
    public int id {get; set;}
    public string firstname {get; set;}
    public string lastname {get; set;}
    public ICollection<Role> roles {get; set;}
}

public class Role{
    public int id {get; set;}
    public string name {get; set;}
    public string resource_type { get; set; }
    public Nullable<int> resource_id { get; set; }
    public System.DateTime created_at { get; set; }
    public System.DateTime updated_at { get; set; }
    public ICollection<User> users {get; set;}
}

In the below example, the DBContext object as created as db. Create the Users model object and add roles for the User. This will automatically make an entry in the join table.

//Find existing user
var user = db.users.Find(userid);

//Remove existing role
DBMODELS.role role = db.roles.Include("users").Where(x => x.resource_id == moduleid && x.resource_type == "MyModule" && x.name == "admin").FirstOrDefault();
db.roles.Remove(role);
db.SaveChanges();

//Add new role.
DBMODELS.role newrole = new DBMODELS.role();
newrole.name = "super_admin";
newrole.resource_id = moduleid;
newrole.resource_type = "MyModule";
newrole.created_at = DateTime.UtcNow;
newrole.updated_at = DateTime.UtcNow;
db.roles.Add(newrole);
db.SaveChanges();

user.roles.Add(newrole);
db.SaveChanges();

Eager loading is achieved using the Include() method above.

Resize image preserving aspect ratio in C#

The aspect ratio of an image describes the proportional relationship between its width and its height. For an x:y aspect ratio, if the width is divided into x units of equal length and the height is measured using this same length unit, the height will be measured to be y units.

The below method saves images with different encoder formats of jpeg, png and gif images. You can modify the code for other available formats in C#.

public class ImageUploader
    {

public float Save(Bitmap image, int maxWidth, int maxHeight, int quality, string fileName, string ext)
        {
            // Get the image's original width and height
            int originalWidth = image.Width;
            int originalHeight = image.Height;

            // To preserve the aspect ratio
            float ratioX = (float)maxWidth / (float)originalWidth;
            float ratioY = (float)maxHeight / (float)originalHeight;
            float ratio = Math.Min(ratioX, ratioY);

            float sourceRatio = (float)originalWidth / originalHeight;

            // New width and height based on aspect ratio
            int newWidth = (int)(originalWidth * ratio);
            int newHeight = (int)(originalHeight * ratio);

            // Convert other formats (including CMYK) to RGB.
            Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);

            // Draws the image in the specified size with quality mode set to HighQuality
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.DrawImage(image, 0, 0, newWidth, newHeight);
            }

            ImageCodecInfo imageCodecInfo = null;
            // Get an ImageCodecInfo object that represents the JPEG codec.
            if (ext == ".jpg" || ext == ".jpeg")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Jpeg);
            }
            else if (ext == ".png")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Png);
            }
            else if (ext == ".gif")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Gif);
            }

            // Create an Encoder object for the Quality parameter.
            Encoder encoder = Encoder.Quality;

            // Create an EncoderParameters object. 
            EncoderParameters encoderParameters = new EncoderParameters(1);

            // Save the image as a JPEG file with quality level.
            EncoderParameter encoderParameter = new EncoderParameter(encoder, quality);
            encoderParameters.Param[0] = encoderParameter;
            newImage.Save(uploadsdir + fileName, imageCodecInfo, encoderParameters);

            return sourceRatio;
        }
}
private ImageCodecInfo GetEncoderInfo(ImageFormat format)
        {
            return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid);
        }

Call the code above with the following parameters as below, keeping the following points in mind:

  • SaveImages method below is created keeping in mind, it is written for a WebAPI and the image may be received in the byte array format.
  • Use a very large height value, so the new image is re-sized restricted to new width size for thumb, medium and large sizes based on the aspect ratio.
  • The Quality category specifies the level of compression for an image. When used to construct an EncoderParameter, the range of useful values for the quality category is from 0 to 100. The lower the number specified, the higher the compression and therefore the lower the quality of the image. Zero would give you the lowest quality image and 100 the highest.
public string SaveImages(byte[] imgArr, string filename, string extension, string uploadtype, out float ratio)
        {
            const int THUMB_WIDTH = 120;
            const int MEDIUM_WIDTH = 400;
            const int LARGE_WIDTH = 900;
            const int IMG_HEIGHT = 100000;
            const int IMG_QUALITY = 100;
            ratio = 0.0f;
            string[] extensionwhitelist = new string[] { ".jpg", ".jpeg", ".gif", ".png" };

            ImageUploader uploader = new ImageUploader(uploadtype);
            
            var encfilename = encryptfilename(filename);
            try
            {
                if (!extensionwhitelist.Contains(extension))
                {
                    throw new Exception("Invalid File format.");
                }
                
                TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
                Bitmap bitmapImg = (Bitmap)tc.ConvertFrom(imgArr);

                uploader.SaveOriginal(bitmapImg, IMG_QUALITY, encfilename + extension, extension);
                uploader.Save(bitmapImg, THUMB_WIDTH, IMG_HEIGHT, IMG_QUALITY, "thumb_" + encfilename + extension, extension);
                uploader.Save(bitmapImg, MEDIUM_WIDTH, IMG_HEIGHT, IMG_QUALITY, "medium_" + encfilename + extension, extension);
                ratio = uploader.Save(bitmapImg, LARGE_WIDTH, IMG_HEIGHT, IMG_QUALITY, "large_" + encfilename + extension, extension);
            }
            catch(Exception ex)
            {
                throw new BusinessServiceException("SaveImages", "Failed saving images.", ex);
            }

            return encfilename;
        }

The method encryptfilename can be written using a method of choice for encrypting the filename of the image.

Import and dump data for Postgresql on Windows 10

If you need to dump the schema and data for your Postgresql database, and may be re-import it to another database or share it with someone, you have the pg_dump and psql utility at help. If you’re using Windows 10 64-bit machine, the psql and pg_dump utility is available at the following path: C:\Program Files\PostgreSQL\11\bin.

To dump the data for your database, use the following command replacing the values as required:

pg_dump.exe -U postgres -d testdb -f D:\BackupData\import_dump.sql

To import the database, use the below command:

psql.exe -U USERNAME -d DATABASENAME -f  BACKUP_FILE_NAME.sql

e.g. replace the parameter values for:

username as postgres

database name as testdb

import sql file (using -f switch) as import_dump.sql or provide the complete path to the file.

psql.exe -U postgres -d testdb -f D:\BackupData\import_dump.sql

Install uninstall cocoapods in your iOS Swift app

Cocoapods are third-party libraries that help you do some of the work in your app for you saving your time. These Cocoapods are built with Ruby and is installable with the built-in Ruby on your Mac OS. Search for your required Cocoapod here.

First install on your macOS using the below command in your Mac terminal:

$ sudo gem install cocoapods

Your installed gems list may be a lot longer than shown above as I’ve already installed before.

Next, setup pods with:

$ pods setup --verbose

–verbose is optional, it’ll just show you the progress of the setup.

Once, the setup is completed, let’s install the individual cocoapods. Navigate to the folder of your Project and create the pod file. And then open it for editing with the following commands:

$ cd myapp

$ pod init

$ open -a Xcode podfile

Make changes to your podfile similar to shown above after uncommenting/removing a few lines. The first line tells the minimum supported iOS platform. The general rule of the thumb is to support the last 2 iOS releases. The target is the name of your project.

use_frameworks is required for Swift Projects. The provide the list of pods inside the do block which are required for your app. Make sure the name is correct as selected from the Cocoapods.org site. Please do check if the pods you’re using is well maintained and when was the last time it was updated. Should not be like last updated 4-5 years ago is not a good sign.

Once your changes are done, save the file and run the below command while within the app folder:

$ pod install

From now on, you would want to open your project in Xcode using .xcworkspace in your Project folder instead of .xcodeproj.

To use the pod in your project, just import the pod using the import statement in your class and you can use it as per the documentation e.g.

import VENTokenField
import SVProgressHUD

To uninstall and clean your Project completely from CocoaPods, run the following commands:

$ sudo gem install cocoapods-deintegrate cocoapods-clean
$ pod deintegrate && pod clean
$ rm Podfile

Setup Ruby on Rails on Windows 10 Ubuntu Linux Subsystem with postgresql

Install Linux subsystem on Windows:

We’re going to use Bash on Ubuntu on Windows as it allows you to run Linux on your Windows machine. This only works on 64-bit installations of Windows. Reboot your machine once the installation completes.

Search for Bash in your start menu and follow the installation instructions to get the Ubuntu subsystem installed on Windows 10 which will be downloaded from the Windows Store. Or you can download and install from Windows Store here for Ubuntu 16.04 LTS version. Launch the downloaded version from Windows Store and install it.

You can also use the command as shown below to download and install from Microsoft Store:

Setup the username and password for the Linux subsystem. The user must be a sudoer to use system commands at the root level. Once the installation is completed you’ll be able to search for Bash on Ubuntu on Windows in your start menu.

Note:

If you face any issues and need to uninstall again, open command prompt (not bash):

lxrun /uninstall /full

Then Turn of the Windows feature for Linux subsystem and follow the installation steps again.

Install Ruby:

First, we need to install some dependencies for Ruby environment. Install the latest recommended version. We’re currently working with Ruby 2.5.3 but this may change in future. Run the following commands in Bash (Remove $ sign as this is part of the prompt at the terminal):

$ sudo apt-get update
$ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev postgresql-client-common postgresql-client libpq-dev

If the terminal prompts for confirmation, just press ‘y’. The pre-reqs are required to get Ruby and PostgreSQL installed.

Note: Some of dependencies for postgresql are not mentioned on the gorails blog as it is using mysql.

Install Ruby using ‘rubyenv’ with the following commands:

$ cd
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec $SHELL
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ exec $SHELL
$ rbenv install 2.5.3
$ rbenv global 2.5.3
Finally, check installed version with:
$ ruby -v

Install Bundler:

$ gem install bundler

After bundler install, run the below command:

$ rbenv rehash

Install Rails:

We’ll install the current latest version of Rails 5.2.1.

First, let’s install NodeJS runtime from the official repository that allows us to use Coffeescript and the Asset pipeline in Rails which combines and minifies your javascript to provide a faster production environment.

$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt-get install -y nodejs

Next, install rails:

$ gem install rails -v 5.2.1

Run this to make the Rails executable available:

$ rbenv rehash

You can check the installed rails version as below:

$ rails -v

Setup PostgreSQL:

Download the latest version of PostgreSQL from the as recommended in Official PostgreSQL site. For, Windows 10 64-bit version, use the highlighted version. Download the installer certified by EnterpriseDB for all supported PostgreSQL versions.

This is the full installer that comes with PGAdmin4. Follow the installer steps and note down the username and password used while configuring the installation. The database Server runs using the default port 5432. After the installation completes, run the PostgreSQL Service.

Setup Demo Rails Project:

Let’s create a folder under the C: on Windows which is accessible in Linux under /mnt/c.

$ cd /mnt/c
$ mkdir –p code
$ rails new demoapp –d postgresql
$ cd demoapp

When you change the directory to the demoapp, you’ll find a lot of files created automatically by Rails framework structured using the MVC pattern. This is equivalent to C:\code\demoapp on Windows. In order to further build the app and automatically create the database in PostgreSQL, we need to first modify the config/database.yml file with the correct username and password which was used while installing the PostgreSQL software.

To do this, we can use popular code editor tools like Visual Studio code, Sublime text, Atom etc. We’re going to use Visual Studio Code. You can download and install it here. Open the DemoApp folder in Visual Studio code and find the database.yml under the config folder. Modify the file as shown below. Provide the required password used during installation. This file has the configuration for creating the database under different environments like dev, test and production. Default database.yml format.

Create the database:

The below commands should be run while you’re inside the demoapp folder in Ubuntu Bash.

We can use the rake utility to create and manage the database using the command line tool. Run the below command to create the database:

$ rake db:create

Once the database is up and running, run the rails Server to access the application.

$ rails s

You can visit the website at http://localhost:3000 which is the default port for the app.

You should see a screen like this:

Configure Git (optional):

You can use the Git configuration steps if you’re using version control for your code using GitHub or any other Git Service provider. The general process is to use SSH protocol and creating the public-private key pair. The public key requires to be added in the SSH keys section of the provider with a title while the private key should not be shared. This helps in creating a SSH tunnel from your machine to the provider like GitHub.

$ ssh-keygen -t rsa -b 4096 -C "YOUR@EMAIL.com"

Navigate the .ssh folder outside the demoapp folder:

$ cd .ssh

And copy the rsa public key generated above using text editors like vim or nano.

$ vim id_rsa.pub

You can check if the connection successfully established with your provider account and you should see a success message e.g.

$ ssh –T git@github.com