6

Podążam za this article na MSDN. Najpierw zaimportowałem go do kodu EF.LINQ to Entities nie rozpoznaje metody

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(); 

Model ten jest wielki, ponieważ daje mi testowalności. Jednak prowadzenie kwerend jak ten powyżej rzuca to

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. 

Rozumiem błąd, ale czy jest jakiś sposób, aby tego uniknąć, ale nadal zachować repozytoria dla testowalności?

Odpowiedz

4

Twój SELECT nie może być tłumaczone ze względu na charakter jak IQueryable<T> a praca dostawcy zapytania: zobacz ten wątek, aby uzyskać więcej informacji What is the difference between IQueryable<T> and IEnumerable<T>?

Można „help” dostawcy LINQ dzieląc swój wyraz w jednostkowym sprawozdaniu jak to:

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; 

Albo można pozwolić FindAll() zwracają IEnumerable<T> zamiast IQueryable<T> a następnie oryginalna wyrażenie powinno działać.

+2

dziękuję to działa. IEnumerable jest chciwy. przynosi wszystko w pamięci i robi to później. –

Powiązane problemy