仓储库通用的Linq查找方法

3

我有一个应用程序,使用仓储模式来抽象化数据检索的方式。我计划使用Web服务来检索数据,但是在开发过程中将使用模拟数据。然而,我卡在如何使查找方法正常工作上了。到目前为止,我已经做了以下工作,但我不确定 query.Compile() 是否正确(我找到的示例没有这样做)。我得到一个编译器错误,说Linq的Where方法没有重载,它需要一个 System.Linq.Expressions.Expression。这是我目前的进展:

public async Task<IEnumerable<Customer>> FindAsync(Expression<Func<Customer, bool>> query)
{
    var allCustomers = await GetAllAsync(true);

    return allCustomers.Where(query.Compile());
}

我希望能找到避免检索所有客户然后再应用表达式的方法,但是我不确定如何将表达式传递给REST webservice,以便过滤可以在数据访问层发生。


1
如果您正在从 WebService 获取数据,则需要实现自己的 LINQ 提供程序才能使用 IQueryable:http://msdn.microsoft.com/en-us/library/vstudio/bb546158%28v=vs.110%29.aspx - 假设 WebService 允许过滤数据。 - user2160375
2
这段代码是可以编译通过的。为什么你不直接使用 Func<Customer, bool> 而要用 Expression 呢? - Yuval Itzchakov
1
@YuvalItzchakov 我猜OP想在WebService端进行过滤 - 当使用带有FuncIEnumerable时,所有数据都在客户端获取和过滤。他需要实现自己的LINQ提供程序 - 当WebService支持查询API时。 - user2160375
1
@pwas 对,我漏掉了。谢谢。 - Yuval Itzchakov
谢谢。我还没有解决Web服务的问题(考虑暴露oData或使用业务层作为与使用WCF与oData数据层交互的API)。是否已经有了oData的Linq提供程序? - Mike
很遗憾,Mike - LINQ提供程序通常是为指定的具体服务准备的。这是我的示例:http://1drv.ms/W2tbVf 我已经准备了一个样本虚拟服务,并为TakeWhere实现了LINQ提供程序。我还录制了解释片段,但不幸的是语言记录不是英语。 - user2160375
2个回答

2
我见过的 Repository 模式的实现通常是这样的(使用 Entity Framework):

public class Repository<T> where T : class
{
    private readonly DbSet<T> _queryableBase;

    public Repository(DbSet<T> queryableBase)
    {
        _queryableBase = queryableBase;
    }

    public T Select(IFilter<T> filterClass)
    {
        return filterClass.Filter(_queryableBase.AsQueryable()).First();
    }
    public IEnumerable<T> SelectMany(IFilter<T> filterClass)
    {
        return filterClass.Filter(_queryableBase.AsQueryable());
    }

    public void Delete(T item)
    {
        _queryableBase.Remove(item);
    }

    public void Add(T item)
    {
        _queryableBase.Add(item);
    }
}

然后是过滤器对象:
public interface IFilter<T>
{
    IEnumerable<T> Filter(IEnumerable<T> queryableBase);
}

示例筛选实现:

class FilterChris : IFilter<ATestObject>
{
    public IEnumerable<ATestObject> Filter(IEnumerable<ATestObject> queryableBase)
    {
        return queryableBase.Where(o => o.FirstName == "Chris");
    }
}

public class ATestObject
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

请注意,过滤器可以链接在一起使用。

1
在某些时候,我希望能够找出如何避免检索所有客户并应用表达式,但不确定如何将表达式传递给REST webservice以便过滤可以发生在数据访问层。假设您的客户端应用程序是用C#编写的,您可以使用breeze-sharp。

http://www.breezejs.com/breeze-sharp-documentation/query-examples#whereSimple

BreezeSharp可以与任何支持HTTP和JSON的服务进行通信。 您是否正在使用由Entity Framework支持的Web API、OData或MVC提供SQL Server数据?Breeze具有出色的开箱即用功能。 BreezeSharp允许您在客户端编写如下代码:
var query3 = query1.Where(td => !td.IsArchived && !td.IsDone);
var activeTodos = awaitManager.ExecuteQuery(query3);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接