C# 在LINQtoSQL中,如何将LINQ查询的一部分传递给函数
是否可以将linq查询的一部分传递到函数中? 我想为我的DAL创建一个始终使用相同查询接口的公共接口。比如说,C# 在LINQtoSQL中,如何将LINQ查询的一部分传递给函数,c#,linq,linq-to-sql,expression-trees,C#,Linq,Linq To Sql,Expression Trees,是否可以将linq查询的一部分传递到函数中? 我想为我的DAL创建一个始终使用相同查询接口的公共接口。比如说, List<T> Get(Join j, Where w, Select s){ return currentDataContext<T>.Join(j).Where(w).Select(s).ToList(); } 这可能吗?我想这可以通过表达式树来完成,但我还没有找到它的示例。您可以使用参数并将其作为字符串传递。检查此泛型类: 它基本
List<T> Get(Join j, Where w, Select s){
return currentDataContext<T>.Join(j).Where(w).Select(s).ToList();
}
这可能吗?我想这可以通过表达式树来完成,但我还没有找到它的示例。您可以使用参数并将其作为字符串传递。检查此泛型类:
它基本上使用Func委托应用Where谓词:
//...
public TableView(DataContext dataContext, Expression<Func<TEntity, bool>> predicate)
{
this.table = dataContext.GetTable<TEntity>();
this.baseQuery = table.Where(predicate);
this.predicate = predicate.Compile();
}
//...
嗯,连接是很棘手的,因为很难表达连接-但是像where/select/orderby这样的事情非常简单 实际上,这只是在IQueryable上组合各种LINQ方法的一个例子,它们通常接受某种组合的表达式。因此,带有可选谓词的基本select将是:
public IQueryable<T> Get<T>(
Expression<Func<T,bool>> predicate
) where T : class
{
IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
if (predicate != null) query = query.Where(predicate);
return query;
}
使用哪种Northwind进行查询:
SELECT COUNT(*) AS [value]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[Country] = @p0
在查询中包含select投影的问题在于,最终会得到多个泛型类型。由于您经常希望投影是匿名类型,因此很难指定投影类型anonymous和表类型,并且它不可调用
实际上,我想知道写这种方法是否有很多好处。我可能会坚持使用基本方法:
public IQueryable<T> Get<T>() where T : class
{
return (IQueryable<T>)GetTable(typeof(T));
}
或者,如果您确实希望包含orderby和投影,那么扩展方法是最实用的方法;然后,您不需要指定原始源t,这使得它在与anon类型混合时不可调用:
public static class QueryExtension
{
public static IQueryable<TProjection>
Get<TSource, TProjection, TOrderKey>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> where, // optional
Expression<Func<TSource, TProjection>> select,
Expression<Func<TProjection, TOrderKey>> orderBy)
{
if (where != null) source = source.Where(where);
return source.Select(select).OrderBy(orderBy);
}
}
然后考虑一个DAL方法,例如:
public List<string> Countries()
{
return Customers.Get(
x=>x.CompanyName != "",
x=>x.Country,
x=>x).Distinct().ToList();
}
再次使用Northwind:
SELECT DISTINCT [t0].[Country]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CompanyName] <> @p0
您可以使用Linq示例提供的动态表达式库,通过此扩展库,您可以传递where等的Linq子句 可从此处下载
Marc Gravell♦, 和往常一样,它提供了一个非常有见地的答案,但我真的认为,在大多数情况下,使用接受IQueryables并添加限制的方法是可行的,它们使代码更清晰,易于维护。例如:
using(var ctx = new MyDataContext(CONN))
{
ctx.Log = Console.Out;
int frCount = ctx.Get<Customer>(c => c.Country == "France").Count();
}
//Join
public static IQueryable<IContract> AllContracts(this IQueryable<IAccount> accounts, ISession s ) {
return from a in accounts
from contract in s.Query<IContract()
where (a.Id == contract.AccountId)
select contract;
}
//Where
public static IQueryable<IContract> Active(this IQueryable<IContract> contracts) {
return from contract in contracts
where (contract.Active == true)
select contract;
}
然后你可以像这样混合搭配:
IQueryable<IContract> activeContracts = s.Query<IAccount>()
.Where(o => o.Name == "XXX")
.GetContracts(s)
.Active();
我在这里使用扩展方法和NHiberante的LINQ提供的查询方法,但是这可以很容易地在没有静态方法和任何LINQ提供程序的情况下重写 事实上,我对此有点担心。它编译谓词的事实意味着它将始终加载整个表,然后对其上的对象执行LINQ。这是非常低效的。
//Join
public static IQueryable<IContract> AllContracts(this IQueryable<IAccount> accounts, ISession s ) {
return from a in accounts
from contract in s.Query<IContract()
where (a.Id == contract.AccountId)
select contract;
}
//Where
public static IQueryable<IContract> Active(this IQueryable<IContract> contracts) {
return from contract in contracts
where (contract.Active == true)
select contract;
}
IQueryable<IContract> activeContracts = s.Query<IAccount>()
.Where(o => o.Name == "XXX")
.GetContracts(s)
.Active();