How can I create a generic data repository for my Entity Framework solution?
I recently created a quick console application that required CRUD activities on a SQL database. I had a few tables to update and did not want the headache of creating multiple items in my DAL.
Enter a generic data repository.
The code is pretty simple:
1. Create a base interface for the CRUD operations
public interface IGenericDataRepository<T> where T : class
{
List<T> GetAll(params Expression<Func<T, object>>[] navigationProperties);
List<T> GetList(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
T GetSingle(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
void Add(params T[] items);
void Update(params T[] items);
void Remove(params T[] items);
void RemoveAll(string tableName);
void ExecuteSQLCommand(string sqlCommand, SqlParameter[] parameters);
}
2. Create your Entity Framework data model. I called my ImportEntities.
3. Create a repository class that uses the interface
public class GenericDataRepository<T> : IGenericDataRepository<T> where T : class
{
public virtual List<T> GetAll(params Expression<Func<T, object>>[] navigationProperties)
{
List<T> list;
using (var context = new ImportEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
list = dbQuery
.AsNoTracking()
.ToList<T>();
}
return list;
}
public virtual List<T> GetList(Func<T, bool> where,
params Expression<Func<T, object>>[] navigationProperties)
{
List<T> list;
using (var context = new ImportEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
list = dbQuery
.AsNoTracking()
.Where(where)
.ToList<T>();
}
return list;
}
public virtual T GetSingle(Func<T, bool> where,
params Expression<Func<T, object>>[] navigationProperties)
{
T item = null;
using (var context = new ImportEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
item = dbQuery
.AsNoTracking() //Don't track any changes for the selected item
.FirstOrDefault(where); //Apply where clause
}
return item;
}
public virtual void Add(params T[] items)
{
try
{
using (var context = new ImportEntities())
{
foreach (T item in items)
{
context.Entry(item).State = EntityState.Added;
}
context.SaveChanges();
}
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Console.WriteLine("Property: {0} Error: {1}",
validationError.PropertyName,
validationError.ErrorMessage);
}
Console.ReadLine();
}
}
}
public virtual void Update(params T[] items)
{
using (var context = new ImportEntities())
{
foreach (T item in items)
{
context.Entry(item).State = EntityState.Modified;
}
context.SaveChanges();
}
}
public virtual void Remove(params T[] items)
{
using (var context = new ImportEntities())
{
foreach (T item in items)
{
context.Entry(item).State = EntityState.Deleted;
}
context.SaveChanges();
}
}
public virtual void RemoveAll(string tableName)
{
using (var context = new ImportEntities())
{
context.Database.ExecuteSqlCommand(string.Format("TRUNCATE TABLE [{0}]", tableName));
}
}
public virtual void ExecuteSQLCommand(string sqlCommand, SqlParameter[] parameters)
{
using (var context = new ImportEntities())
{
context.Database.ExecuteSqlCommand(sqlCommand, parameters);
}
}
}
4. Now, we can access the repository in code: For example, I have a table called 'TempTable' configured with my Entity Framework data model, I can then instantiate the repository like so:
var repository = new GenericDataRepository<TempTable>();
and use it as follows:
- clear the list:
repository.RemoveAll("TempTable");
- add an item:
repository,add(new TempTable() { Id = 1, Name = "test" });
- execute a stored procedure:
var parameters = new SqlParameter[]
{
new SqlParameter("ExecutionInstance",Guid.NewGuid()),
new SqlParameter("Sequence", 1)
};
repository.ExecuteSQLCommand("dbo.MyProc @ExecutionInstance, @Sequence", parameters);
Enter a generic data repository.
The code is pretty simple:
1. Create a base interface for the CRUD operations
public interface IGenericDataRepository<T> where T : class
{
List<T> GetAll(params Expression<Func<T, object>>[] navigationProperties);
List<T> GetList(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
T GetSingle(Func<T, bool> where, params Expression<Func<T, object>>[] navigationProperties);
void Add(params T[] items);
void Update(params T[] items);
void Remove(params T[] items);
void RemoveAll(string tableName);
void ExecuteSQLCommand(string sqlCommand, SqlParameter[] parameters);
}
2. Create your Entity Framework data model. I called my ImportEntities.
3. Create a repository class that uses the interface
public class GenericDataRepository<T> : IGenericDataRepository<T> where T : class
{
public virtual List<T> GetAll(params Expression<Func<T, object>>[] navigationProperties)
{
List<T> list;
using (var context = new ImportEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
list = dbQuery
.AsNoTracking()
.ToList<T>();
}
return list;
}
public virtual List<T> GetList(Func<T, bool> where,
params Expression<Func<T, object>>[] navigationProperties)
{
List<T> list;
using (var context = new ImportEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
list = dbQuery
.AsNoTracking()
.Where(where)
.ToList<T>();
}
return list;
}
public virtual T GetSingle(Func<T, bool> where,
params Expression<Func<T, object>>[] navigationProperties)
{
T item = null;
using (var context = new ImportEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
item = dbQuery
.AsNoTracking() //Don't track any changes for the selected item
.FirstOrDefault(where); //Apply where clause
}
return item;
}
public virtual void Add(params T[] items)
{
try
{
using (var context = new ImportEntities())
{
foreach (T item in items)
{
context.Entry(item).State = EntityState.Added;
}
context.SaveChanges();
}
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Console.WriteLine("Property: {0} Error: {1}",
validationError.PropertyName,
validationError.ErrorMessage);
}
Console.ReadLine();
}
}
}
public virtual void Update(params T[] items)
{
using (var context = new ImportEntities())
{
foreach (T item in items)
{
context.Entry(item).State = EntityState.Modified;
}
context.SaveChanges();
}
}
public virtual void Remove(params T[] items)
{
using (var context = new ImportEntities())
{
foreach (T item in items)
{
context.Entry(item).State = EntityState.Deleted;
}
context.SaveChanges();
}
}
public virtual void RemoveAll(string tableName)
{
using (var context = new ImportEntities())
{
context.Database.ExecuteSqlCommand(string.Format("TRUNCATE TABLE [{0}]", tableName));
}
}
public virtual void ExecuteSQLCommand(string sqlCommand, SqlParameter[] parameters)
{
using (var context = new ImportEntities())
{
context.Database.ExecuteSqlCommand(sqlCommand, parameters);
}
}
}
4. Now, we can access the repository in code: For example, I have a table called 'TempTable' configured with my Entity Framework data model, I can then instantiate the repository like so:
var repository = new GenericDataRepository<TempTable>();
and use it as follows:
- clear the list:
repository.RemoveAll("TempTable");
- add an item:
repository,add(new TempTable() { Id = 1, Name = "test" });
- execute a stored procedure:
var parameters = new SqlParameter[]
{
new SqlParameter("ExecutionInstance",Guid.NewGuid()),
new SqlParameter("Sequence", 1)
};
repository.ExecuteSQLCommand("dbo.MyProc @ExecutionInstance, @Sequence", parameters);
Comments
Post a Comment