13.3 LINQ和数据库操作
LINQ查询技术主要是用于操作关系型数据库的,其中LINQ to Entity是LINQ操作数据库中最重要的技术。它提供运行时的基础结构,将关系数据库作为对象进行管理。本节将着重介绍有关LINQ to Entity的使用方法。
13.3.1 LINQ TO Entity
LINQ to Entity是ADO.NET EntityFramework和LINQ结合的产物。它将关系数据库模型映射到编程语言所表示的对象模型。开发人员通过使用对象模型来实现对数据库数据的操作。在操作过程中,LINQ to Entity会将对象模型中的语言集成查询转换为SQL,然后将它们发送到数据库进行执行。当数据库返回结果时,LINQ to Entity会将它们转换成相应的编程语言处理对象。
使用LINQ to Entity可以完成的常用的数据库操作包括:
● 选择
● 插入
● 更新
● 删除
以上四大操作包含了数据库应用程序的所有功能,LINQ to Entity全部能够实现。因此,在掌握了LINQ技术后,读者就不需要再针对特殊的数据库学习特别的SQL语法了。
LINQ to Entity的使用主要可以分为两大步骤:
(1)创建实体数据模型(Entity Data Model,EDM)
要实现LINQ to Entity,首先必须根据现有关系数据库的元数据创建实体数据模型。实体数据模型就是按照开发人员所用的编程语言来表示的数据库。有了这个表示数据库的对象模型,才能创建查询语句操作数据库。
(2)使用实体数据模型
在创建了实体数据模型后,就可以在该模型中请求和操作数据了。使用模型的基本步骤为:
● 创建查询以便从数据库中检索信息。
● 重写Insert、Update和Delete的默认方法。
● 设置适当的选项以便检测和报告可能产生的并发冲突。
● 建立继承层次结构。
● 提供合适的用户界面。
● 调试并测试应用程序。
以上只是使用实体数据模型的基本步骤,其中很多步骤都是可选的,在实际应用中,有些步骤可能并不会每次都需要使用到。
13.3.2 实体数据模型的创建
实体数据模型是关系数据库在编程语言中表示的数据模型,对实体数据模型的操作就是对关系数据库的操作。表13-1列举了LINQ to Entity实体数据模型中的元素与关系数据库中元素的对应关系。
表13-1 LINQ to Entity实体数据模型中的基本元素
创建实体数据模型方法有三种:
(1)使用实体数据模型设计器,实体数据模型设计器提供了从现有数据库创建实体数据模型的可视化操作,它被集成在Visual Studio 2012中,比较适用于小型或中型的数据库。
(2)使用SQLMetal代码生成工具,这个工具适合大型数据库的开发,因此对于普通读者来说,这种方法并不常用了。
(3)直接编写创建实体对象的代码。这种方法在有实体数据模型设计器的情况下不建议使用。
在实际开发过程中,几乎都使用第1种方法来创建对象模型,所以这里只介绍如何使用最常用的实体数据模型设计器创建对象模型。
实体数据模型设计器(O/R设计器)提供了一个可视化设计界面,用于在应用程序中创建映射到数据库中的对象模型。同时,它还生成一个强类型ObjectContext,用于在实体类与数据库之间发送和接收数据。强类型ObjectContext表示LINQ to Entity框架的主入口点,充当SQL Server数据库与映射到数据库的LINQ to Entity实体类之间管道。
ObjectContext类包含用于连接数据库以及操作数据库数据的连接字符串信息和方法,也可以将新方法添加到ObjectContext类。ObjectContext类提供了如表13-2和表13-3所示的属性和方法。
表13-2 ObjectContext类的属性
表13-3 DataContext类的方法
(续表)
【实例13-3】ADO.NET实体数据模型的创建
本实例演示如何使用实体数据模型设计器来创建一个ADO.NET实体数据模型,数据库和表使用前几章中的db_news和tb_News,具体实现步骤如下:
01 启动Visual Studio 2012,创建一个ASP.NET Web空应用程序,命名为“实例13-3”。
02 用右键单击网站名称“实例13-3”,在弹出的快捷菜单中选择“添加”|“添加新项”,弹出如图13-4所示的“添加新项”对话框。
图13-4 “添加新项”对话框
03 选择“已安装模板”下的“Visual C#”模板,并在模板文件列表中选中“ADO.NET实体数据模型”,然后在“名称”文本框输入该文件的名称Model.edmx,最后单击“添加”按钮,弹出如图13-5所示的“提示”对话框。
图13-5 “提示”对话框
04 单击“是”按钮,弹出如图13-6所示的“实体数据模型向导”对话框。
图13-6 “实体数据模型向导”对话框
05 在“模型将包含哪些内容”列表中选择“从数据库生成”选项,单击“下一步”按钮,进入如图13-7所示的“选择您的数据连接”对话框。
图13-7 “选择您的数据连接”对话框
06 单击“新建连接”按钮,弹出如图13-8所示的“连接属性”对话框。
图13-8 “连接属性”对话框
07 在“数据源”文本框中输入Microsoft SQL Serve(SqlClient),在“服务器名”下拉列表中选择自己SQL Server服务器的名称,选择“选择或输入数据库名称”单选按钮,在其下拉列表中选中db_news数据库的名称,最后单击“确定”按钮,返回如图13-9所示的“实体数据模型向导”对话框。
图13-9 “实体数据模型向导”对话框
08 选中“将Web.Config中的实体连接设置另存为”多选框,单击“下一步”按钮,弹出如图13-10所示的“选择您的数据库对象和设置”对话框。
图13-10 “选择您的数据库对象和设置”对话框
09 展开“表”|dbo,选择tb_News数据表,最后单击“完成”按钮。
10 此时在网站根目录下会生成如图13-11所示的“App_Code文件夹”,将在该文件夹中会自动生成一些文件,将其中的Model.Context.tt和Model.tt从程序中删除,剩下的是一个包含模型信息的Model.edmx文件。该文件由实体设计器使用,通过该设计器可以以图形方式查看和编辑概念模型和映射。此外,实体数据模型设计器还会创建一个源代码文件Model.Designer.cs,其中包含基于.edmx文件的CSDL内容而生成的类。该源代码文件是自动生成的,并在.edmx文件发生更改时随之更新。
图13-11 生成的文件
11 单击Model.edmx文件,出现图13-12“实体数据模型设计器”界面,看到可视化的tb_News数据表。使用实体设计器可以直观地创建和修改实体、关联、映射和继承关系,还可以验证.edmx文件。
图13-12 实体模型设计器
12 在“实体数据模型设计器”界面的空白处单击右键,在弹出的快捷菜单中选择“属性”命令,弹出如图13-13所示的实体属性模型“属性”窗口。
图13-13 “属性”窗口
13 将“代码生成”属性组下的“代码生成策略”的属性值从“无”修改为“默认值”。
14 打开文件Model.Designer.cs,可以看到该文件自动生成了包含实体数据模型的实体类以及强类型ObjectContext的定义。至此,实体数据模型就创建完毕了,在页面代码中就可以像使用其他类型的类一样使用它。
创建了实体数据模型后,就可以查询数据库了。LINQ to Entity会将编写的查询转换成等效的SQL语句,然后把它们发送到服务器进行处理。具体来说,应用程序将使用LINQ to Entity API来请求查询执行,LINQ to Entity提供程序,随后会将查询转换成SQL文本,并委托ADO提供程序执行。ADO提供程序将查询结果作为DataReader返回,而LINQ to Entity提供程序将ADO结果转换成用户对象的IQueryable集合。
LINQ to Entity中的查询与LINQ中的查询使用相同的语法,只不过它们操作的对象有所差异,LINQ to Entity查询中引用的对象是映射到数据库中的元素,示例代码如下:
上面的代码中第1行定义声明强类型ObjectContext的对象data。第2、3行定义隐藏变量NewsQuery,通过LINQ查询从实体类News中获取查询到的数据。
13.3.3 ASP.NET 4.5模型绑定方式
ASP.NET 4.5版本之前的数据绑定方式,要采用“%# Eval("LastName") %”的绑定表达式,然后使用数据控件的DataSource属性绑定提供的数据源和使用DataBind()方法。比如需要将数据绑定到Repeater控件,通常会采用如下的实现方式:
上面的代码中在第3行~第8行的<ItemTemplate>模板中的第5行和第6行使用了绑定表达式绑定了数据表中的ID和Title两个字段的内容。
后台数据绑定方式不变,沿用DataSource提供数据源和DataBind(),如下面的代码:
上面代码中第2行实例化一个实体数据模型对象db,第3行调用db对象中数据表News对象的ToList方法获得表中所有的记录作为Repeater1控件的数据源。第4行调用Repeater1控件的DataBind()方法绑定数据并显示。
但是,现在ASP.NET 4.5中提供了强类型数据绑定新特性,通过控件的ModelType属性和SelcteMothed属性来实现新的绑定方式。
ModelType属性指定要绑定的强类型对象全限定名,提供了新的数据绑定表示式<%#: Item.属性%>。
SeleteMothed属性获取或设置由数据绑定控件调用以插入数据的方法或函数的名称。
上面的Repeater控件采用新的绑定方式后的代码如下:
上面代码中第1行中的ModelType属性设置了要绑定的对象的名称Model.News。所以在第4行和第5行可以使用“<%#: Item.属性%>”的方式来绑定该对象中的成员,也就是数据表中的字段。第3行通过SelectMethod属性设置获得数据的方法Repeater1_GetDate。
后台数据绑定方式也发生了很大地改变,不再沿用DataSource提供数据源和DataBind()方法,而是定义一个方法,不再需要在页面Page_Load事件中处理数据了,如下面的代码:
上面的代码中,第1行定义一个Repeater1_GetDate,该方法名与Repeater1控件的SelectMethod属性设置获得数据的方法必须一致,它返回一个IQueryable的集合,在该集合中保存了从实体数据模型中查询出来的结果。
【实例13-4】查询数据库
本实例演示利用上例中创建的实体数据模型从数据表tb_News中查询从第11条记录开始的5条数据并使用新的绑定方式进行GridView控件的显示,具体实现步骤如下。
01 继续上面“实例13-3”的开发,在“实例13-4”中创建一个名为Default.aspx的窗体文件。
02 单击网站的根目录下Default.aspx文件,打开“视图设计器”,进入“源视图”,在<form>和</form>标记间添加如下代码:
上面的代码中第2行定义一个服务器列表控件GridView1,设置SelectMethod属性,在后台代码文件中定义的方法GridView1_GetData来获得要显示的数据。第3行设置ItemType属性设置绑定的项类型是实体数据模型实体类tb_News。
03 在GridView控件右上方有一个向右的黑色小三角,单击这个小按钮打开“GridView任务”列表,选择“自动套用格式”。弹出“自动套用格式”对话框,在左边的选择架构列表中选中“蓝黑2”,最后,单击“确定”按钮。
04 单击网站根目录下的Default.aspx.cs文件,编写代码如下:
上面的代码中第1行自定义GridView1_GetData返回从数据表中查询到的内容。第2行定义声明强类型db_newsEntities对象db。第3行创建LINQ查询语句,查询News表中从第11条记录开始的5条数据。第4行返回查询到的IQueryable集合。
05 按快捷键Ctrl+F5运行程序,运行结果如图13-14所示。
图13-14 运行结果
13.3.4 更改数据库
除了可以查询数据库,开发人员还可以使用LINQ to Entity对数据库进行更改操作,包括插入、更新和删除。在LINQ to Entity中执行插入、更新和删除操作的方法是:向实体数据模型中添加对象、更改和移除实体模型中的对象,然后LINQ to Entity会把所做的操作转化成SQL,最后把这些SQL提交到数据库执行。在默认情况下,LINQ to Entity就会自动生成动态SQL来实现插入、读取、更新和操作。也可以自定义SQL来实现一些特殊的功能。
1.LINQ插入数据库
使用LINQ向数据库插入行的操作步骤如下:
● 创建一个要提交到数据库的新对象。
● 将这个新对象添加到与数据库中目标数据表关联的LINQ to Entity Table集合。
● 将更改提交到数据库。
2.LINQ修改数据库
使用LINQ修改数据库数据的操作步骤如下:
● 查询数据库中要更新的数据行。
● 对得到的LINQ to Entity对象中成员值进行更改。
● 将更改提交到数据库。
3.LINQ删除数据库
可以通过将对应的LINQ to Entity对象从相关的集合中去除来实现删除数据库中的行。不过,LINQ to Entity不支持且无法识别级联删除操作。如果要在对行有约束的表中删除数据,则必须符合下面的条件之一:
● 在数据库的外键约束中设置ON DELETE CASCADE规则。
● 编写代码先删除约束表的级联关系。
删除数据库中数据行的操作步骤如下:
● 查询数据库中要删除的行。
● 调用DeleteObject()方法。
● 将更改提交到数据库。
【实例13-5】更改数据库
本实例演示利用“实例13-3”中创建的实体数据模型,接受用户选择的数据进行修改和删除的操作,具体实现步骤如下:
01 启动Visual Studio 2012,创建一个ASP.NET Web空应用程序,命名为“实例13-5”。
02 按照“实例13-3”的步骤,创建实体数据模型。
03 在“实例13-5”中创建名为Default.aspx的窗体文件。
04 单击网站的根目录下Default.aspx文件,进入到“视图设计器”。从“工具箱”分别拖动一个GridView控件、一个DropDownList1控件、4个TextBox控件和两个Button控件到“设计视图”中。
05 打开“GridView任务”列表,选择“自动套用格式”。弹出“自动套用格式”对话框,在左边的选择架构列表中选中“蓝黑2”,单击“确定”按钮。
06 单击网站根目录下的Default.aspx.cs文件,编写关键代码如下。
上面的代码中第1行声明一个实体数据模型对象db。第2行处理页面Page加载事件Load的方法。第3行和第4行利用LINQ查询表达式从数据库查询tb_News表中最后5条数据记录。第5行将查询的结果作为下拉列表控件DropDownList1的数据源。第8行调用DropDownList1控件的DataBind方法绑定数据。第9行将查询的结果作为列表控件GridView1的数据源。第10行调用GridView1控件的DataBind方法绑定数据。
第12行定义处理“更新”按钮Button1单击事件Click的方法。第17行定义一个tb_News实体类的对象news,该对象就是用户所选择要修改的一条新闻记录,通过LIQN表达式查询下拉列表中所选的新闻编号ID来获得,第18行~第22行将用户输入在文本框中的内容赋值给news对象中的各个成员。第23行把调用实体数据对象SaveChanges方法对数据库的数据进行更新。
第25行定义处理“删除”按钮Button2单击事件Click的方法。第27行定义一个tb_News实体类的对象news,该对象就是用户所选择要删除的一条新闻记录,通过LIQN表达式查询下拉列表中所选的新闻编号ID来获得,第28行调用方法DeleteObject删除获得对象。第29行把更改提交到数据库对数据进行删除。
07 按快捷键Ctrl+F5运行程序,运行结果如图13-15所示。
图13-15 运行结果