C#操作LINQ to SQL组件进行数据库建模的基本教程
建立实体类
使用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,编写相关代码如下,实现增删改查:
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,如下:
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:
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,内容如下:
<?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:
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:
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,下面的示例程序对对象和属性按其功能进行了必要的分组,代码中也有详尽的注释。代码如下:
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等方法。
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(); } } }
程序运行结果如下: