C# 查询IQueryable是否与ORM完全解耦?

C# 查询IQueryable是否与ORM完全解耦?,c#,entity-framework,nhibernate,orm,iqueryable,C#,Entity Framework,Nhibernate,Orm,Iqueryable,我可能完全误解了IQueryable引擎盖下发生的事情,所以如果我错了,我欢迎纠正 我的数据库中有一个日志表,我想使用KendoUI表在前端web应用程序上查看它 这些javascript组件非常灵活;他们可以根据多个维度来定位和限制通过连接传递的数据。。。例如,我可以获得按日志日期组织的前100条记录,过滤用户所在的调试或信息 这对IEnumerable对象很有效。。。但是表中有很多LogEntry对象,我认为随着logs表的不断增长,这应该表现得非常糟糕 我想实现如下服务: public i

我可能完全误解了IQueryable引擎盖下发生的事情,所以如果我错了,我欢迎纠正

我的数据库中有一个日志表,我想使用KendoUI表在前端web应用程序上查看它

这些javascript组件非常灵活;他们可以根据多个维度来定位和限制通过连接传递的数据。。。例如,我可以获得按日志日期组织的前100条记录,过滤用户所在的调试或信息

这对IEnumerable对象很有效。。。但是表中有很多LogEntry对象,我认为随着logs表的不断增长,这应该表现得非常糟糕

我想实现如下服务:

public interface ILogBrowsingService
{
    IQueryable<LogEntry> Logs { get; }
}
。。。在另一个程序集中使用ORM EF的具体实现中,NHibernate、Telerik DataAccess尚未决定将查询的大部分繁重工作卸载到数据库服务器。我基本上是针对服务中暴露的IQueryable运行查询。。。但是,我认为我很快就会遇到问题,因为此服务将在其自己的特定于服务的数据上下文和自己的Linq-To-X实现下运行。我相信我在这个实现中会遇到一些问题,比如数据库上下文生命周期、IQueryable支持等等

我当时的想法是针对通用IQueryable捕获查询,并将其作为参数传递到服务中,以针对具体实现进行重播,但我不知道该如何做,但大致如下:

public interface ILogBrowsingService
{
    IList<LogEntry> GetLogEntryQueryResults(IQuery<LogEntry> query);
}
我不知道伊奎里会是什么样子


我真的不想尝试编写一个服务/存储库模式,该模式将包含此表的多种可搜索性排列。我是在想象一个没有问题的问题,还是有一个正确的方法来完成我想做的事情,完全不受ORM后端的影响?

我使用了这个称为查询对象模式的模式,我相信它与您在这里尝试实现的类似。该模式不会自动记录查询并为您重放查询,但它允许您以可以重放查询的方式编写查询,还可以避免类似于存储库的模式的副作用

我们需要定义一个接口IQuery,如下所示

现在,我们可以根据要从数据库中获取的内容编写非常具体的查询。您可以组合多个筛选条件,也可以为每个条件编写单独的查询。与规范模式不同,此模式不能将多个不同的查询组合在一起

然后我们需要一些东西来运行这个查询。QueryRunner很方便

public class QueryRunner : IRunQuery
{
    private readonly ISession session;

    public QueryRunner(ISession session)
    {
        this.session = session;
    }

    public IEnumerable<T> Run<T>(IQuery<T> query) where T : EntityBase<T>
    {
        return query.Run(session.Query<T>());
    }
}
在您的服务类中,如果您正在使用依赖项注入,则可以获取对IRunQuery的依赖项,并创建要执行的查询对象的实例,并将其传递到IRunQuery实例的Run方法中


这可能不适合你的情况,但你可以尝试一下这种模式,看看它是否能把你带到任何地方

只是不要用IQueryable。返回IEnumerable,不要告诉存储库如何做某事。只是要求做一些事情。回购方将知道如何使用EF和其他方返还实体。保持简单,并将特定的标准传递给特定查询的简单对象。
public class LogEntriesByTypeQuery : IQuery<LogEntry>
{
    private readonly int type;

    public LogEntriesByTypeQuery(string type)
    {
        this.type = type;
    }

    public IEnumerable<LogEntry> Run(IQueryable<LogEntry> logEntries)
    {
        return (from e in logEntries
            where e.Type == type
            select e).ToList();
    }
}
public class QueryRunner : IRunQuery
{
    private readonly ISession session;

    public QueryRunner(ISession session)
    {
        this.session = session;
    }

    public IEnumerable<T> Run<T>(IQuery<T> query) where T : EntityBase<T>
    {
        return query.Run(session.Query<T>());
    }
}