建立实体类
使用linq to sql时,需要首先建立用于映射数据库对象的模型,也就是实体类。在运行时,linq to sql 根据linq表达式或查询运算符生成sql语句,发送到数据库进行操作。数据库返回后,linq to sql负责将结果转换成实体类对象。
建立实体类的方法有很多,例如linq to sql设计器,手动编码建立,使用xml文件映射,使用命令行工具sqlmetal生成等。其中最方便的就是linq to sql设计器。
1.使用linq to sql设计器建立实体类
在一个示例用的demo控制台程序中添加一个“基于服务的数据库”database1.mdf,建立一张tb_guestinfo的表。该表的详细如下:
下面的所有建立方式,都用的这个数据库。
在项目中添加一个linq to sql类,采用默认的名称dataclasses1.dbml,如下:
将tb_guestinfo表拖到界面上,保存。
ok,编写相关代码如下,实现增删改查:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
using system; using system.collections.generic; using system.linq; using system.text; namespace linq_to_sql自定义数据库和实体类 { /// <summary> /// 实体类的建立___1.vs建立实体类 /// </summary> class program { static void main( string [] args) { // dataclasses1datacontext dc = new dataclasses1datacontext(); //1.查询 iqueryable<tb_guestinfo> query = from p in dc.tb_guestinfo where p.name != "xxx" select p; foreach (var g in query) { console.writeline( "{0} {1} {2} {3}" ,g.id,g.name,g.age ,g.tel ); } console.writeline( "-----------------" ); console.readkey( false ); //2.增加一条记录 tb_guestinfo ginfo = new tb_guestinfo() { id = 9, name = "m&m" , age = 40, tel = "135****5555" }; dc.tb_guestinfo.insertonsubmit(ginfo); dc.submitchanges(); foreach (var g in query) { console.writeline( "{0} {1} {2} {3}" ,g.id , g.name, g.age, g.tel); } console.writeline( "-----------------" ); console.readkey( false ); //3.删除 var query_itemtodelete = from g in dc.tb_guestinfo where g.name == "m&m" select g; foreach (var g in query_itemtodelete) { dc.tb_guestinfo.deleteonsubmit(g); } dc.submitchanges(); foreach (var g in query) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "-----------------" ); console.readkey( false ); //4.修改 var query_itemtoupdate = from g in dc.tb_guestinfo where g.name.contains( "debuglzq" ) select g; foreach (var g in query_itemtoupdate) { g.name = g.name + "a" ; } dc.submitchanges(); foreach (var g in query) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "-----------------" ); console.readkey( false ); } } } |
程序运行结果如下:
2.手动建立实体类
实体类在多数情况下可以通过linq to sql类设计器建立,当然动手建立一个简单的实体类也不是难事,并且可以更好的学习linq to sql的对象模型。数据库依然是前面的示例数据库。
在项目中添加一个类guestinfoentity.cs,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
using system; using system.collections.generic; using system.linq; using system.text; using system.data.linq.mapping; namespace datacontexdemo { /// <summary> /// 手动建立实体类 /// </summary> [table(name= "tb_guestinfo" )] class guestinfoentity { [column(isprimarykey= true ,dbtype= "int not null identity" ,isdbgenerated= true ,name= "id" )] public int id { get ; set ; } [column(dbtype = "nvarchar(20)" , name = "name" )] public string name{ get ; set ;} [column(dbtype = "int" , name = "age" )] public int age { get ; set ; } [column(dbtype = "nvarchar(20)" , name = "tel" )] public string tel { get ; set ; } } } |
编写示例代码,注意需要引入system.data.linq.dll:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
using system; using system.collections.generic; using system.linq; using system.text; using system.data.linq; //关注 namespace datacontexdemo { class program { static void main( string [] args) { //2.手动建立实体类 // //连接字符串 string constring = @"data source=.\sqlexpress;attachdbfilename=e:\visual studio 2010\linq_to_sql\linq_to_sql自定义数据库和实体类\database1.mdf;integrated security=true;user instance=true" ; datacontext dc = new datacontext(constring); table<guestinfoentity> tb = dc.gettable<guestinfoentity>(); var query = tb.asenumerable(); foreach (var q in query) { console.writeline( "{0} {1} {2} {3}" ,q.id,q.name,q.age,q.tel ); } console.readkey(); } } } |
程序运行如下:
3.使用xml映射文件建立实体类
实体类的映射除了使用内联attribute外,还可以建立一个包含映射信息的xml文件,此文件生成system.data.linq.mapping.xmlmappingsource对象,作为datacontext对象构造方法的参数。
这个xml文件只有一个根节点---database元素,用来映射的数据库信息。database元素包含一个或多个table元素,用于映射数据库表的信息,table元素由一个type元素和多个column元素(或association元素)组成。type元素用来指定实体类,column元素用来指定列信息,association元素用来映射数据库关系。
在项目中添加一个xml文件,采用默认名称xmlfile1.xml,内容如下:
1
2
3
4
5
6
7
8
9
10
11
|
<? xml version = "1.0" encoding = "utf-8" ?> < database name = "database1" xmlns = "http://schemas.microsoft.com/linqtosql/mapping/2007" > <!--数据库名称可随意;名称空间一定要加上--> < table name = "tb_guestinfo" > <!--数据库中表的名称--> < type name = "linqtosql建立实体类_xml.guestinfoentity" > <!--太bt了,居然要全名;guestinfoentity居然不行--> < column name = "id" member = "id" dbtype = "int not null identity" isprimarykey = "true" /> < column name = "name" member = "name" dbtype = "nvarchar(20)" /> < column name = "age" member = "age" dbtype = "int" /> < column name = "tel" member = "tel" dbtype = "nvarchar(20)" /> </ type > </ table > </ database > |
这个xml文件包含类全部的映射信息,下面建立映射的类guestinfoentity.cs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
using system; using system.collections.generic; using system.linq; using system.text; namespace linqtosql建立实体类_xml { public class guestinfoentity { public int id { get ; set ; } public string name { get ; set ; } public int age { get ; set ; } public string tel { get ; set ; } } } |
编写示例代码,同样需要引入system.data.linq.dll:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
using system; using system.collections.generic; using system.linq; using system.text; using system.data.linq; using system.data.linq.mapping; using system.io; // namespace linqtosql建立实体类_xml { class program { static void main( string [] args) { string constring = @"data source=.\sqlexpress;attachdbfilename=e:\visual studio 2010\linq_to_sql\linq_to_sql自定义数据库和实体类\database1.mdf;integrated security=true;user instance=true" ; xmlmappingsource map = xmlmappingsource.fromxml(file.readalltext( "xmlfile1.xml" )); datacontext dc = new datacontext(constring, map); table<guestinfoentity> tb = dc.gettable<guestinfoentity>(); var query = tb.asenumerable(); foreach (var g in query) { console.writeline( "{0} {1} {2} {3}" ,g.id,g.name,g.age,g.tel ); } console.readkey(); } } } |
程序的运行如下:
用于数据库连接的datacontext对象成员
datacontext类位于system.data.linq.dll程序集中的system.data.linq名称空间下。在linq to sql中负责实体对象和数据库之间的数据交换及其他数据库操作,还负责把数据库中的数据映射成实体类的实例。
datacontext是linq to sql操作实体类建立后紧接着需要操作的对象。本文总结其常用函数和属性的作用及常用用法,实体类是上一节的guestinfo.cs类,数据库也采用上一节的数据库database1.mdb,下面的示例程序对对象和属性按其功能进行了必要的分组,代码中也有详尽的注释。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
using system; using system.collections.generic; using system.linq; using system.text; using system.data.linq; using system.io; using system.data.sqlclient; namespace datacontext对象成员 { /// <summary> /// 用于数据库连接的datacontext类成员 /// </summary> class program { static void main( string [] args) { //连接字符串 string constring = @"data source=.\sqlexpress;attachdbfilename=e:\visual studio 2010\linq_to_sql\linq_to_sql自定义数据库和实体类\database1.mdf;integrated security=true;user instance=true" ; //1.构造函数 datacontext dc = new datacontext(constring); //2.gettable table<guestinfoentity> table = dc.gettable<guestinfoentity>(); var query = table.asenumerable(); foreach (var g in query) { console.writeline( "{0} {1} {2} {3}" ,g.id,g.name,g.age,g.tel ); } console.writeline( "-----------------" ); console.readkey(); string filename = @"e:\visual studio 2010\linq_to_sql\linq_to_sql自定义数据库和实体类\database1.mdf" ; //3.databaseexists、deletedatabase、createdatabase if (dc.databaseexists()) { console.writeline( "数据库文件已经存在." ); dc.deletedatabase(); } dc.createdatabase(); if (dc.databaseexists()) { console.writeline( "{0} 数据库文件创建成功." ,path.getfilename(filename )); } console.writeline( "-----------------" ); console.readkey(); //4_1.executecommand 作为linq补充直接用sql指令操作数据库 dc.executecommand( "insert into tb_guestinfo(name,age,tel) values({0},{1},{2})" , "debuglzq" ,25, "198****1336" ); foreach (var r in dc.gettable<guestinfoentity>()) { console.writeline( "{0} {1} {2} {3}" ,r.id,r.name,r.age,r.tel ); } console.writeline( "-----------------" ); console.readkey(); //4_2.executequery 作为linq补充直接用sql指令操作数据库 var rows= dc.executequery<guestinfoentity>( "select * from tb_guestinfo" ); foreach (var r in rows) { console.writeline( "{0} {1} {2} {3}" , r.id, r.name, r.age, r.tel); } console.writeline( "-----------------" ); console.readkey(); //4_3translate 将dbreader转换为linq对象 string querystring = "select * from tb_guestinfo" ; sqlconnection connection = new sqlconnection(constring); sqlcommand cmd = new sqlcommand(querystring, connection); connection.open(); var result = dc.translate<guestinfoentity>(cmd.executereader()); //ado.net转换linq foreach (var r in result) { console.writeline( "{0} {1} {2} {3}" , r.id, r.name, r.age, r.tel); } connection.close(); console.writeline( "-----------------" ); console.readkey(); //5.submitchanges 应用修改 var firstrow = (from p in dc.gettable<guestinfoentity>() select p).first(); firstrow.name =firstrow.name + "a" ; dc.submitchanges(); //应用修改 foreach (var r in dc.gettable<guestinfoentity>() ) { console.writeline( "{0} {1} {2} {3}" , r.id, r.name, r.age, r.tel); } console.writeline( "-----------------" ); console.readkey(); //6.getchangeset方法 返回datacontext对象插入、删除、修改过的对象 changeset cs = dc.getchangeset(); foreach (var r in cs.updates ) { guestinfoentity t = r as guestinfoentity; console.writeline( "{0} {1} {2} {3}" , t.id,t.name,t.age,t.tel ); } console.writeline( "-----------------" ); console.readkey(); //7.refresh刷新实体对象 var row1=(from g in dc.gettable<guestinfoentity>() select g).first(); row1.age = row1.age + 5; dc.submitchanges(); dc.refresh(refreshmode.overwritecurrentvalues, row1); // foreach (var r in dc.gettable<guestinfoentity>()) { console.writeline( "{0} {1} {2} {3}" , r.id, r.name, r.age, r.tel); } console.writeline( "7-----------------" ); console.readkey(); //changeconflicts属性 返回datacontext操作数据库时产生的并发冲突合集 //transaction属性 设置或返回datacontext跟其他ado.net程序共享的事物对象 //objecttrackingenabled属性 开启或关闭datacontext实体对象的状态跟踪 //8.log属性 返回datacontext产生的sql命令 dc.log = console. out ; //控制台输出datacontext产生的sql语句 foreach (var r in dc.gettable<guestinfoentity>()) { console.writeline( "{0} {1} {2} {3}" , r.id, r.name, r.age, r.tel); } console.writeline( "-----------------" ); console.readkey(); } } } |
程序中的注释很详细,不再赘述。
程序的运行结果如下:
操作单一表格的table<tentity>类
前面介绍了datacontext类,它可以用来映射和连接数据库,执行sql命令,跟踪实体对象的状态。
下面介绍table<tentity>表示表格记录,它是一个泛型集合类,它的元素就是表格实体对象。它提供一组方法,对元素进行添加删除操作,并可以通过datacontext将这些操作保存到数据库。
表还是前面的那张表,在项目中添加了一个linq to sql类。重点是insertonsubmit、deleteonsubmit等方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
using system; using system.collections.generic; using system.linq; using system.text; namespace linq_to_sql_table { /// <summary> /// 操作单一表格的table<tentity>类 /// </summary> class program { static void main( string [] args) { //1.a.attach附加实体 dataclasses1datacontext dc1 = new dataclasses1datacontext(); tb_guestinfo guset = new tb_guestinfo() { id=1, name = "debuglzq" , age = 35, tel = "138****8888" }; dc1.tb_guestinfo.attach(guset); //这样的attach仅仅附加实体,数据库没有更新 dc1.submitchanges(); //显示附加成功 foreach (var g in dc1.tb_guestinfo) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "---------" ); //显示数据库没有更新 dataclasses1datacontext dc2 = new dataclasses1datacontext(); foreach (var g in dc2.tb_guestinfo) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "------------------------" ); console.readkey(); //2.insertonsubmit dc2.tb_guestinfo.insertonsubmit(guset); dc2.submitchanges(); foreach (var g in dc2.tb_guestinfo) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "------------------------" ); console.readkey(); //2b.insertallonsubmit 插入集合 list<tb_guestinfo> lst = new list<tb_guestinfo>() { new tb_guestinfo(){ name= "aa" , age=25,tel= "133****3333" }, new tb_guestinfo(){ name= "bb" , age=25,tel= "135****5555" } }; dc2.tb_guestinfo.insertallonsubmit(lst); dc2.submitchanges(); foreach (var g in dc2.tb_guestinfo) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "------------------------" ); console.readkey(); // //3.deleteonsubmit tb_guestinfo entity = (from g in dc2.tb_guestinfo where g.name == "aa" select g).single(); dc2.tb_guestinfo.deleteonsubmit(entity); // dc2.submitchanges(); foreach (var g in dc2.tb_guestinfo) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "------------------------" ); console.readkey(); //3b.deleteallonsubmit ienumerable<tb_guestinfo> entitys = from g in dc2.tb_guestinfo where g.name == "aa" || g.name == "bb" select g; dc2.tb_guestinfo.deleteallonsubmit(entitys); dc2.submitchanges(); foreach (var g in dc2.tb_guestinfo) { console.writeline( "{0} {1} {2} {3}" , g.id, g.name, g.age, g.tel); } console.writeline( "------------------------" ); console.readkey(); } } } |
程序运行结果如下: