6

Estoy siguiendo this article en MSDN. Lo porté a EF Code First.LINQ to Entities no reconoce el método

public interface IUnitOfWork 
{ 
    IRepository<Employee> Employees { get; } 
    IRepository<TimeCard> TimeCards { get; } 
    void Commit(); 
} 

public class HrContext : DbContext 
{ 
    public DbSet<Employee> Employees { get; set; } 
    public DbSet<TimeCard> TimeCards { get; set; } 
    protected override void OnModelCreating(ModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Employee>() 
        .HasMany(e => e.TimeCards) 
        .WithOptional(tc => tc.Employee); 
    } 
} 

public class SqlRepository<T> : IRepository<T> 
    where T : class 
{ 
    private readonly DbSet<T> entitySet; 
    public SqlRepository(DbContext context) 
    { 
     this.entitySet = context.Set<T>(); 
    } 
    public void Add(T newEntity) 
    { 
     this.entitySet.Add(newEntity); 
    } 
    public IQueryable<T> FindAll() 
    { 
     return this.entitySet; 
    } 
    public T FindById(params object[] keys) 
    { 
     return this.entitySet.Find(keys); 
    } 
    public IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate) 
    { 
     return this.entitySet.Where(predicate); 
    } 
    public void Remove(T entity) 
    { 
     this.entitySet.Remove(entity); 
    } 
} 

public class SqlUnitOfWork : IUnitOfWork, IDisposable 
{ 
    private readonly HrContext context; 
    private IRepository<Employee> employees; 
    private IRepository<TimeCard> timeCards; 
    public SqlUnitOfWork() 
    { 
     this.context = new HrContext(); 
    } 
    public IRepository<Employee> Employees 
    { 
     get 
     { 
      return new SqlRepository<Employee>(context); 
     } 
    } 
    public IRepository<TimeCard> TimeCards 
    { 
     get 
     { 
      return new SqlRepository<TimeCard>(context); 
     } 
    } 
    public void Commit() 
    { 
     this.context.SaveChanges(); 
    } 
    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

var query = from e in unitOfWork.Employees.FindAll() 
      from tc in unitOfWork.TimeCards.FindAll() 
      where tc.Employee.Id == e.Id && e.Name.StartsWith("C") 
      select tc; 
var timeCards = query.ToList(); 

Este modelo es excelente ya que me da la capacidad de prueba. Sin embargo, la ejecución de consultas como la de arriba lanza este

LINQ to Entities does not recognize the method 
'System.Linq.IQueryable`1[DomainModel.Models.TimeCard] FindAll()' 
    method, and this method cannot be translated into a store expression. 

entiendo el error, pero ¿hay alguna manera de evitarlo, pero aún así mantener los repositorios de la capacidad de prueba?

Respuesta

4

Su instrucción de selección no se puede traducir debido a la naturaleza de cómo IQueryable<T> y el trabajo de los proveedores de consulta: ver este tema para obtener más información What is the difference between IQueryable<T> and IEnumerable<T>?

Usted puede 'ayuda' del proveedor de LINQ dividiendo su expresión en declaraciones por separado como esto:

var ems = unitOfWork.Employees.FindAll(); 
var tcs = unitOfWork.TimeCards.FindAll(); 

var query = from e in ems 
      from tc in tcs 
      where tc.Employee.Id == e.Id && e.Name.StartsWith("C") 
      select tc; 

o puede dejar que FindAll() devuelven IEnumerable<T> en lugar de IQueryable<T> y luego su expresión original debería funcionar.

+2

gracias, funciona. IEnumerable es codicioso sin embargo. trae todo en la memoria y se une después. –

Cuestiones relacionadas