开发者社区> 醉意人间> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

LinQ&EF任我行(一)--LinQ to SQL (转)

简介: LinQ家族五大成员:LinQ to Objects - 默认功能,用来实现对内存中集合对象的查询LinQ to SQL - 针对SQL Server的查询,它是一个带有可视化的操作界面的ORM工具LinQ to DataSet - 对强类型化或弱类型化的DataSet或独立的DataTable进行查询LinQ to Entity - 对实体框架中EDM定义的实体集合进行查询。
+关注继续查看

LinQ家族五大成员:
LinQ to Objects - 默认功能,用来实现对内存中集合对象的查询
LinQ to SQL - 针对SQL Server的查询,它是一个带有可视化的操作界面的ORM工具
LinQ to DataSet - 对强类型化或弱类型化的DataSet或独立的DataTable进行查询
LinQ to Entity - 对实体框架中EDM定义的实体集合进行查询。
LinQ to XML - 对XML文档进行查询创建等操作。


C#语法与LinQ相关的新增功能


1.隐式强类型变量
在C#3.0中可以使用var关键字隐式定义强类型局部变量。



《图1》
这里的var关键字定义变量与JavaScript定义变量看起来很像但二者有着本质的区别。
JavaScript定义的变量是弱类型的变量,也可理解为是一种通用类型的变量,它可以容纳各种类型的值,还可以在运行过程中动态修改其中的内容类型。下面这种写法在JavaScript中是正确的:
var obj = 3.14;
obj = "hello world";

C#中的var则是种强类型的变量,它在定义的时候会确定数据类型,分配内存空间。上面这两名代码在C#3.0中会报错,因为第一句已经把obj定义为double型的变量,第二句把字符串赋值给double是错误的操作。

隐式强类型并不能有效简化我的书写的代码,但当我们在用它来动态接收一些未知类型的数据的时候就显虽得很强大。在隐式强类型变量出现前,我们一般是使用object型变量来接收这种未知类型的数据的。

2.对象初始化
这个功能可以有效简化类的getter和setter部份的代码,还可以只使用一行表达式语句实现对象的实例化与初始化操作
如定义实例类时可以使用如下代码,没有必要再把成员变量和属性分别定义了。
public class LineItem
{
    public int OrderID { get; set; }
    public int ProductID { get; set; }
    public short Quantity { get; set; }
    public string QuantityPerUnit { get; set; }
    public decimal UnitPrice { get; set; }
    public float Discount { get; set; }
}
实例化LineItem对象,并为它赋值
var line3 = new LineItem { OrderID = 11000, ProductID = 61, Quantity = 30, QuantityPerUnit = “12 1-kg cartons”, UnitPrice = 15.55M, Discount = 0.15F };

3.数组初始化
var LineItems = new[]
{
    new LineItem {OrderID = 11000, ProductID = 11, Quantity = 10,
        QuantityPerUnit = “24 500-g bottles”, UnitPrice = 15.55M, Discount = 0.0F},
    new LineItem {OrderID = 11000, ProductID = 21, Quantity = 20,
        QuantityPerUnit = “12 1-kg cartons”, UnitPrice = 20.2M, Discount = 0.1F},
    new LineItem {OrderID = 11000, ProductID = 31, Quantity = 30,
        QuantityPerUnit = “24 1-kg bags”, UnitPrice = 25.45M, Discount = 0.15F}
};

4.集合初始化
var LineItemsList = new List < LineItem >
{
    new LineItem {OrderID = 11000, ProductID = 11, Quantity = 10,
       QuantityPerUnit = “24 500-g bottles”, UnitPrice = 15.55M, Discount = 0.0F},
    new LineItem {OrderID = 11000, ProductID = 21, Quantity = 20,
       QuantityPerUnit = “12 1-kg cartons”, UnitPrice = 20.2M, Discount = 0.1F},
    new LineItem {OrderID = 11000, ProductID = 31, Quantity = 30,
       QuantityPerUnit = “24 1-kg bags”, UnitPrice = 25.45M, Discount = 0.15F}
};

5.匿名类型
过去我们要生成对象时,必须事先定义该对象的类,然后使用new关键字来实例化该类。匿名类型简化定义类的这个过程,我们可以使用new关键字直接把类的定义,类的实例化放在一个表达式语句中
如:
var obj = new
{
    Name = "zhangsan",
    Age = 18,
    URL = "
http://hi.baidu.com/grayworm"
};
Console.WriteLine(obj.Name + obj.Age + obj.URL);

匿名类型主要用在LinQ to SQL中对字段的投影功能上:
var query = from i in LineItems select new { i.OrderID, i.ProductID, i.UnitPrice }

6.扩展方法
扩展方法就是为现有的类追加我们自定义的方法。在C#3.0的集成开发环境中,我们会发现带有向下箭头的方法,这些方法是我们在C#2.0中所没有见到的方法,这些方法就是我们所谓的“扩展方法”,它是C#3.0在C#2.0的基础上新增的一系列的方法,当然我们也可以为内置类添加我们自己的主扩展方法。



《图2》
例如在string中有个Length()扩展方法,它用来取得字符串的长度,但当字符串是null的时候调用该字符串的Length()时候会抛出异常。下面我们为String类添加一个自定义的方法LengthNullable(),如果字符串为null不抛出异常,而返回-1:
代码如下:
static class ExtensionMethods
{
    public static int LengthNullable(this string test)
    {
        if (test != null)
        {
            return test.Length;
        }
        else
        {
            return -1
        }
    }
}
C#3.0的扩展方法需要单独写在一个public static的类中,并且扩展方法也应当用public static修饰。扩展方法的参数有三部份组成(this string test),第一部份是this关键字,它用来告诉编译器该方法是扩展方法;第二部份是该方法要追加到哪个类上,上面的例子代表该LengthNullable方法要追加到string类中去;第三部份是该类的实例名。
public static class ExtentionMethods
{
     public static void Sleep(this Ren r)
     {
         Console.WriteLine(r.Name+" is sleeping.....");
     }
}
public class Ren
{
     public string Name { get; set; }
     public int Age { get; set; }
     public void Speak()
     {
         Console.WriteLine(Name + Age);
     }
}
如果扩展方法与实例方法重名了,那在调用的时候只会调用到实例方法。

7.匿名方法
在C#2.0中就存在匿名方法,但很少有程序员去使用匿名方法,因为它的语法有些怪异。匿名方法的主要用法:使用代理来替代一些简单的方法。
大家都知道代理是指向方法的指针。如:
//声明代理
delegate void Delegate(int x);        
//定义方法
void DoSomething(int y) { /* Something */ };        
//把代理指向方法
Delegate d = obj.DoSomething;

这里的方法有方法名--DoSomething,而匿名方法可以让代理直接指向一个没有名子的方法。如:
//声明代理
delegate void Delegate(int x);
//把代理指向一个匿名方法。
Del d = delegate(int y) { /* Do Something */ };

匿名方法可以使代码变得更紧凑、更清晰、占用更少的资源。由于匿名方法与代理的关系很密切,所以有的人也称之为“匿名代理”。
在泛型集合List<T>中就有几个方法Exists()、Find()、FindAll()、RemoveAll()等方法,在Array类中也有类似的方法。这些方法都能够对泛型集合进行简单的查询操作,它们的方法签名如下所示:



《图3》
每个方法中都有个参数Predicate<T>,这个参数是个泛型代理,用来筛选数据。
如果不使用匿名方法,那我们得这样编写代码:
static bool HighUnitPrice(LineItem i)
{
    if (i.UnitPrice > 25M)
        return true;
    else
        return false;
}
LineItem obj = Array.Find(LineItems, HighUnitPrice);
先定义一个方法HighUnitPrice(LineItem i),然后在Array.Find()的参数Predicate<T>中调用该方法。如果有了匿名方法就不用再单独定义HighUnitPrice(LineItem i)方法了。
如:
var anon = LineItemsList.Find(
delegate(LineItem i)
{
   return i.UnitPrice > = 25M;
}

);
在C#3.0中的好多地方都用到了匿名方法,匿名方法是理解Lambda表达式的基础。

8. Lambda表达式
Lambda表达式就是用很少的代码来实现匿名方法。
语法格式:
参数列表=>表达式

下面我们来看看如何把匿名方法转换为Lambda表达式:
匿名方法:
delegate(LineItem i) { return i.UnitPrice >= 25M; }
第一步:删除关键字delegate,变为
(LineItem i) { return i.UnitPrice >= 25M; }
第二步:把花括号{}替的换为Lambda运算符=>,变为
(LineItem i) => return i.UnitPrice >= 25M;
第三步:去掉return和分号,语句变成表达式
(LineItem i) => i.UnitPrice >= 25M
第四步:由于编译器会自动进行类型推断,所以我们还可以把LineItem去掉。
i => i.UnitPrice >= 25M
这样就把匿名方法变成了Lambda表达式。
var anon = LineItemsList.Find( i = > i.UnitPrice > = 25M );
由此可见Lambda表达式是由Lambda运算符分割开的两部份组成。右边部分代表运算的语句块,左边部分代表的是运算需要的参数。

9.标准查询操作(Standard Query Operators SQO)
标准查询操作是对IEnumerable<T>接口追加的一系列的扩展方法。通过这些扩展方法对实现IEnumerable<T>接口的集合、数组进行一系列的查询操作。一些比较常用的扩展方法有Where()/OrderBy()/Select()等,LinQ标准查询操作我们将在后面详细阐述。
LinQ中的from关键字并不是扩展方法,因此它不是SQO。from只是为in关键字后的序列指定一个别名。
C#3.0的查询表达式是以一个或多个“from 别名 in 序列名”子句开始,以select或group子句结束。而join/let/where/orderby等子句是可选的,需要写在from和select/group子句中间。

下面是对内存中List<productList>集合进行查询的例子
var noStock = from p in productList
              where p.UnitsInStock == 0
              orderby p.Category, p.ProductID
              select new { p.ProductID, p.Category, p.ProductName };
编译器会自动把上面的表达式语句翻译成下面的链式方法调用,在链式方法调用中使用的就是lambda表达式
var noStock = productList
    .Where(p = > p.UnitsInStock == 0)
    .OrderBy(p = > p.Category)
    .ThenBy(p = > p.ProductID)
    .Select(p = > new { p.ProductID, p.Category, p.ProductName });

10.IQueryable<T>接口
IQueryable<T>类型不是集合,他们是支持多态、优化、动态查询功能的LinQ查询序列,它能够把标准化查询操作(SQO)转换成表达式树。简而言之,IQueryable<T>接收的对象不是集合,而是查询表达式树。
我们可以使用IQueryable<T>的ToList()方法来把查询序列变成List<T>类型,使用ToArray()方法把查询序列变成数组类型。
IEnumerable<T>接口中有个AsQueryable()方法,该方法返回的是也IQueryable<T>类型。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
在EF中使用SQL执行简单高效的增删查操作
随着平台数据的积累,对于数据访问的速度要求愈来愈高。优化后台访问性能,将是之后的一个重点任务。 但是,后台在项目开发初期采用的是Abp(Lite DDD)框架,集成EnityFramework。因为之前的项目经验有用过EF,对于开发者编码来说,着实高效。
1154 0
.Net框架搭建之1、SQL Server EF MVC简单三层框架
.Net简单三层框架简介 简单三层框架,是.Net开发中最最基础的框架了,由 数据访问层、逻辑处理层、表示层组成。
905 0
验证EF的Code First自动添加数据库到SQL SERVER
一、 原理分析     Database First先设计数据库后设计程序,程序高度依赖于数据库中的表。EF的Code First是可以自动添加数据库到SQL SERVER。
828 0
MVC EF 执行SQL语句
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来。 十年河东十年河西,莫欺少年穷 学无止境,精益求精 闲着没事,看了一篇关于LINQ和SQL对比的文章,网友们也是积极发言,有人说LINQ简单,维护了程序的可读性,易用性。
2234 0
MiniProfiler工具介绍(监控EF生成的SQL语句)--EF,迷你监控器,哈哈哈
十年河东,十年河西,莫欺少年穷... 今天是抄袭的别人的博客,不过我感觉蛮好,挺有用,特别是老板让你优化EF项目SQL耗时的情况下,你可以采用这种方式来优化你的LINQ。 时间很宝贵,废话还是不多说,直接入主题   MiniProfiler是一款针对.NET, Ruby, Go and Node.js的性能分析的轻量级程序。
2462 0
VS2017调用SQL server 2019 和C++连接语句字符串
VS2017调用SQL server 2019 和C++连接语句字符串
0 0
函数计算 Python 连接 SQL Server
函数计算 Python 连接 SQL Server 自制脑图
0 0
SQL Server 2000 函数使用---CAST 和 CONVERT
日期格式样式,借以将 datetime 或 smalldatetime 数据转换为字符数据(nchar、nvarchar、char、varchar、nchar 或 nvarchar 数据类型);或者字符串格式样式,借以将 float、real、money 或 smallmoney 数据转换为字符数据(nchar、nvarchar、char、varchar、nchar 或 nvarchar 数据类型)。
0 0
+关注
醉意人间
喜欢GIS,喜欢将GIS技术在中国推广
文章
问答
文章排行榜
最热
最新
相关电子书
更多
用SQL做数据分析
立即下载
阿里云流计算 Flink SQL 核心功能解密
立即下载
Comparison of Spark SQL with Hive
立即下载