6

我在MSDN上關注this article。我將它移植到EF Code First。LINQ to Entities不識別方法

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

這種模式是偉大的,因爲它給了我可測試性。但是,運行查詢像上面的拋出這個

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. 

我理解的錯誤,但有什麼辦法,以避免它,但仍保持庫的可測試性?

回答

4

你的SELECT語句不能轉換由於如何IQueryable<T>和查詢提供工作性質:看到這個線程的詳細信息What is the difference between IQueryable<T> and IEnumerable<T>?

你可以「幫助」通過把你的表達到像單獨的語句中的LINQ提供程序這樣的:

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; 

或者你可以讓的FindAll()返回IEnumerable<T>代替IQueryable<T>,然後你的原始表達式應該工作。

+2

謝謝你的工作。儘管IEnumerable是貪婪的。它將所有內容都帶入內存,並在之後進行加入。 – 2011-01-23 00:35:39

相關問題