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.