编写高质量代码改善C#程序的157个建议——建议29:区别LINQ查询中的IEnumerable<T>和IQueryable<T>...

建议29:区别LINQ查询中的IEnumerable<T>和IQueryable<T>

LINQ查询一共提供了两类扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展;Queryable类,它针对继承了IQueryable<T>接口的集合类进行扩扎。接口IQueryable<T>也是继承了IEnumerable<T>接口的,所以,致使两个接口的方法在很大程度上时一致的。

 

LINQ查询从功能上来讲实际上可分为3类:LINQ to OBJECTS、LINQ to SQL、LINQ to XML。设计两套接口的目的在于区分对待LINQ to OBJECTS、LINQ to SQL,两者对于查询的处理在内部使用的是完全不同的机制。针对LINQ to OBJECTS时,使用Enumerable中的扩展方法对本地集合进行排序和查询等操作,查询参数接受的是Func<>。Func<>叫做谓语表达式,相当于一个委托。针对LINQ to SQL时,则使用Queryable中的扩展方法,它接受的是Expression<>。Expression<>用于包装Func<>。LINQ to SQL最终会将表达式树转换成相应的SQL语句,然后在数据库中执行。

 

简单的说:本地数据源用IEnumerable<T>,远程数据源用IQueryable<T>。

 

在使用IEnumerable<T>和IQueryable<T>的时候还需要注意,IEnumerable<T>查询的逻辑可言直接用我们自定义的方法,而IQueryable<T>则不能使用自定义的方法,它必须先生成表达式树,查询由LINQ to SQL引擎处理。在使用IQueryable<T>查询的时候,若果使用自定义方法,则会抛出异常。

            DataContext ctx = new DataContext("server=192.168.0.102;database=Temp;uid=sa;pwd=sa123");
            Table<Person> persons = ctx.GetTable<Person>();
            var temp1 = from p in persons where OlderThan20(p.Age) select p;
            foreach (var item in temp1)
            {
                Console.WriteLine(string.Format("Name:{0}\tAge:{1}", item.Name, item.Age));
            }

抛出异常NotSupportedException:方法“Boolean OlderThan20(Int32)”不支持转换为SQL。

但是,如果我们将查询转换成一个IEnumerable<T>查询,这种模式是支持的:

            List<int> list = new List<int>() { 17, 18, 19, 20, 21, 22, };
            var temp2 = from c in list where OlderTan20(c) select c;

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

转载于:https://www.cnblogs.com/jesselzj/p/4731547.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# ,可以使用泛型方法和类型参数来实现动态查询任意类型的 `List<T>` 数据。下面是一个示例代码: ```csharp using System; using System.Collections.Generic; using System.Linq; class Program { static void Main(string[] args) { List<int> intData = new List<int> { 1, 2, 3, 4 }; List<string> stringData = new List<string> { "Tom", "Jerry", "Mary", "John" }; int intResult = DynamicQuery<int>(intData, x => x > 2); Console.WriteLine($"Int result: {intResult}"); string stringResult = DynamicQuery<string>(stringData, x => x.StartsWith("J")); Console.WriteLine($"String result: {stringResult}"); } static T DynamicQuery<T>(List<T> data, Func<T, bool> predicate) { return data.Where(predicate).FirstOrDefault(); } } ``` 在这个示例,我们定义了一个泛型方法 `DynamicQuery`,它接受一个类型参数 `T` 和一个 `List<T>` 类型的数据 `data`,以及一个 `Func<T, bool>` 类型的谓词表达式 `predicate`。在方法内部,我们使用 LINQ 查询的 `Where` 方法和 `FirstOrDefault` 方法来实现动态查询。由于 `T` 是任意类型,因此可以对任意类型的数据进行动态查询。 在 `Main` 方法,我们分别定义了一个 `List<int>` 类型的数据 `intData` 和一个 `List<string>` 类型的数据 `stringData`,然后分别调用 `DynamicQuery` 方法,传入不同的数据和谓词表达式,即可完成动态查询。 需要注意的是,在使用泛型方法和类型参数进行动态查询时,需要熟悉泛型和委托的语法和用法,才能正确使用这种技术。 希望这个答案能够解决您的问题。如果您有其他问题,可以继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值