Вы можете реализовать собственный репозиторий в своем слое данных, и вот так его проще использовать.
Например
IRepository.cs
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
namespace Persistence.Repository
{
public interface IRepository<T>
{
#region IRepository<T> Members
/// <summary>
/// Retorna un objeto del tipo AsQueryable
/// </summary>
/// <returns></returns>
IQueryable<T> AsQueryable();
/// <summary>
/// Retorna un objeto del tipo AsQueryable y acepta como parámetro las relaciones a incluir
/// </summary>
/// <param name="includeProperties"></param>
/// <returns></returns>
IEnumerable<T> GetAll(params Expression<Func<T, object>>[] includeProperties);
IEnumerable<T> ThenInclude(params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Retorna un objeto del tipo AsQueryable bajo una condición que especifiques como parámetro
/// </summary>
/// <param name="where"></param>
/// <param name="includeProperties"></param>
/// <returns></returns>
IEnumerable<T> Find(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Retorna una entidad bajo una condición especificada
/// </summary>
/// <param name="where"></param>
/// <param name="includeProperties"></param>
/// <returns></returns>
T Single(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Retorna una entidad bajo una condición especificada o null sino encontrara registros
/// </summary>
/// <param name="where"></param>
/// <param name="includeProperties"></param>
/// <returns></returns>
T SingleOrDefault(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Retorna la primera entidad encontrada bajo una condición especificada
/// </summary>
/// <param name="where"></param>
/// <param name="includeProperties"></param>
/// <returns></returns>
T First(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Retorna la primera entidad encontrada bajo una condición especificada o null sino encontrara registros
/// </summary>
/// <param name="where"></param>
/// <param name="includeProperties"></param>
/// <returns></returns>
T FirstOrDefault(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Retorna la primera entidad encontrada bajo una condición especificada o new sino encontrara registros
/// </summary>
/// <param name="where"></param>
/// <param name="includeProperties"></param>
/// <returns></returns>
T FirstOrNew(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties);
/// <summary>
/// Elimina una entidad
/// </summary>
/// <param name="entity"></param>
void Delete(T entity);
/// <summary>
/// Elimina varias entidades
/// </summary>
/// <param name="entity"></param>
void DeleteRange(IEnumerable<T> entities);
/// <summary>
/// Registra una entidad
/// </summary>
/// <param name="entity"></param>
void Insert(T entity);
/// <summary>
/// Actualiza una entidad
/// </summary>
/// <param name="entity"></param>
void Update(T entity);
/// <summary>
/// Registra varias entidades
/// </summary>
/// <param name="entity"></param>
void Insert(IEnumerable<T> entities);
/// <summary>
/// Actualiza varias entidades
/// </summary>
/// <param name="entity"></param>
void Update(IEnumerable<T> entities);
T FirstOrDefault();
T FirstOrNew();
double Max(Func<T, double> field, Expression<Func<T, bool>> where);
double Max(Func<T, double> field);
#endregion
#region SQL Queries
/// <summary>
/// Ejecuta un query personalizado
/// </summary>
/// <param name="entity"></param>
IQueryable<T> SelectQuery(string query, params object[] parameters);
int ExecuteSqlCommand(string query, params object[] parameters);
/// <summary>
/// Ejecuta un query personalizado y espera un retorno a cambio
/// </summary>
/// <param name="entity"></param>
IQueryable<I> ExecuteSqlCommand<I>(string query, params object[] parameters)
where I : class;
#endregion
}
}
Репозиторий.cs
using Common.CustomFilters;
using Persistence.DatabaseContext;
using Persistence.DbContextScope;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
namespace Persistence.Repository
{
public class Repository<T> : IRepository<T> where T : class, new()
{
private readonly IAmbientDbContextLocator _ambientDbContextLocator;
public Repository(IAmbientDbContextLocator context)
{
_ambientDbContextLocator = context;
}
private ApplicationDbContext DbContext
{
get
{
var dbContext = _ambientDbContextLocator.Get<ApplicationDbContext>();
if (dbContext == null)
{
throw new InvalidOperationException("No ambient DbContext of type UserManagementDbContext found. This means that this repository method has been called outside of the scope of a DbContextScope. A repository must only be accessed within the scope of a DbContextScope, which takes care of creating the DbContext instances that the repositories need and making them available as ambient contexts. This is what ensures that, for any given DbContext-derived type, the same instance is used throughout the duration of a business transaction. To fix this issue, use IDbContextScopeFactory in your top-level business logic service method to create a DbContextScope that wraps the entire business transaction that your service method implements. Then access this repository within that scope. Refer to the comments in the IDbContextScope.cs file for more details.");
}
return dbContext;
}
}
private IQueryable<T> PerformInclusions(IEnumerable<Expression<Func<T, object>>> includeProperties,
IQueryable<T> query)
{
return includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
}
#region IRepository<T> Members
public IQueryable<T> AsQueryable()
{
return DbContext.Set<T>().AsQueryable();
}
public IEnumerable<T> GetAll(params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
return PerformInclusions(includeProperties, query);
}
public IEnumerable<T> ThenInclude(params Expression<Func<T, object>>[] thenIncludeProperties)
{
IQueryable<T> query = AsQueryable();
foreach (var item in thenIncludeProperties)
{
query = query.Include(item);
}
return query;
}
public IEnumerable<T> Find(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.Where(where);
}
public T Single(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.Single(where);
}
public T SingleOrDefault(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.SingleOrDefault(where);
}
public double Max(Func<T, double> field, Expression<Func<T, bool>> where)
{
IQueryable<T> query = AsQueryable();
return query.Where(where).Max(field);
}
public double Max(Func<T, double> field)
{
IQueryable<T> query = AsQueryable();
try
{
return query.Max(field);
}
catch (Exception)
{
return 0;
}
}
public T First(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.First(where);
}
public T FirstOrDefault(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.FirstOrDefault(where);
}
public T FirstOrNew(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.FirstOrDefault(where) ?? new T();
}
public T FirstOrDefault()
{
IQueryable<T> query = AsQueryable();
return query.FirstOrDefault();
}
public T FirstOrNew()
{
IQueryable<T> query = AsQueryable();
return query.FirstOrDefault() ?? new T();
}
public void Delete(T entity)
{
if (entity is ISoftDeleted)
{
((ISoftDeleted)entity).Deleted = true;
DbContext.Set<T>().Attach(entity);
DbContext.Entry(entity).State = EntityState.Modified;
}
else
{
DbContext.Set<T>().Remove(entity);
}
}
public void DeleteRange(IEnumerable<T> entities)
{
foreach (var entity in entities)
{
if (entity is ISoftDeleted)
{
((ISoftDeleted)entity).Deleted = true;
DbContext.Set<T>().Attach(entity);
DbContext.Entry(entity).State = EntityState.Modified;
}
else
{
DbContext.Entry(entity).State = EntityState.Deleted;
}
}
}
public void Insert(T entity)
{
DbContext.Set<T>().Add(entity);
}
public void Update(T entity)
{
DbContext.Set<T>().Attach(entity);
DbContext.Entry(entity).State = EntityState.Modified;
}
public void Insert(IEnumerable<T> entities)
{
foreach (var e in entities)
{
DbContext.Entry(e).State = EntityState.Added;
}
}
public void Update(IEnumerable<T> entities)
{
foreach (var e in entities)
{
DbContext.Entry(e).State = EntityState.Modified;
}
}
#endregion
#region SQL Queries
public virtual IQueryable<T> SelectQuery(string query, params object[] parameters)
{
return DbContext.Set<T>().SqlQuery(query, parameters).AsQueryable();
}
public virtual int ExecuteSqlCommand(string query, params object[] parameters)
{
return DbContext.Database.ExecuteSqlCommand(query, parameters);
}
public IQueryable<I> ExecuteSqlCommand<I>(string query, params object[] parameters) where I : class
{
return DbContext.Database.SqlQuery<I>(query, parameters).AsQueryable();
}
#endregion
}
}
Если вы хотите реализовать его, вы можете увидеть этот базовый проект, в котором работает этот репозиторий
https://github.com/Anexsoft/asp.net-mvc-5-arquitectura-base/
Вы можете искать Anexoft в Youtubeесть несколько видеороликов, объясняющих слои этого проекта
Надеюсь, он вам поможет.