LINQ to Entities 无法识别该方法

发布于 2024-10-13 01:44:00 字数 2825 浏览 2 评论 0原文

我正在 MSDN 上关注这篇文章。我将其移植到 EF Code First。

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.

错误,但有什么办法可以避免它,但仍然保留存储库以实现可测试性?

I am following this article on MSDN. I ported it to EF Code First.

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

This model is great as it gives me testability. However, running queries like the one above throws this

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.

I understand the error but is there any way to avoid it but still keep the repositories for testability?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蔚蓝源自深海 2024-10-20 01:44:00

由于 IQueryable 和查询提供程序工作方式的性质,您的 select 语句无法翻译:请参阅此线程以获取更多信息 IQueryable和 IQueryable之间有什么区别和 IEnumerable

您可以通过将表达式分成单独的语句来“帮助”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 而不是 < code>IQueryable然后你的原始表达式应该可以工作。

Your select statement cannot be translated due to the nature of how IQueryable<T> and the query providers work: see this thread for more info What is the difference between IQueryable<T> and IEnumerable<T>?

You can 'help' the linq provider by dividing your expression into separate statements like this:

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;

Or you can let FindAll() return IEnumerable<T> instead of IQueryable<T> and then your original expression should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文