我们之前讲的那几节,除了LINQ TO XML是对专门对XML文档操作的以外,其他的那些内容都是为了讲LINQ TO SQL做铺垫的。就像我们在本系列文章开头讲的那样,LINQ的设计理念就是在不同类型的数据之间(关系数据、层次模型数据等)之间实现数据访问的互通有无,为不同的数据类型提供统一的访问接口。前面几节,我们已经循序渐进的把LINQ TO Object和LINQ TO XML给讲完了。这一节就主要讲LINQ TO SQL,也就是实现对数据库的查询。
那么什么是LINQ TO SQL呢?LINQ TO SQL是包含在.NET Framework的中的一种 ORM (对象关系映射),ORM 允许你使用 .NET 的类来对关系数据库进行建模,并且可以使用LINQ对数据库中的数据进行查询、更新、添加、删除。除此之外,它还提供了对事务、视图、存储过程的支持。为集成数据校验和业务层逻辑到数据模型中提供了一种简单的实现方式。也许有人会问那什么是“ORM”呢?简单的讲“ORM就是关系映射”,我们知道关系型数据库中的关系型数据和面向对象语言中的对象其实是业务实体的两种表现形式,在内存中表现为对象,而在数据库中表现为关系型数据。ORM可以使得关系型数据和对象之间可以以自己熟悉的方式表示与对方的关系,对象——关系映射一般以中间件形式存在,主要为实现程序对象到关系型数据库数据的自动映射。其中LINQ TO SQL中是使用实体类来映射数据库中的物理表,数据库中的实体类和物理表相映射,实体类属性和物理表中的列相映射,这样就可以很好的把对象和关系数据结合起来了。
在Visual Studio 中微软为我们提供了多种建立对象、关系映射的方法。这里我们使用LINQ TO SQL设计器来进行实例演示。
首先在SQL Server里新建数据库LinqTest,并创建如下表:
然后新建一个Windows窗体应用程序,
界面布局如下:
在当前项目下添加文件夹Add_Data,在该文件夹下添加Linq to Sql类文件
如图:
命名为:LinqToSql.dbml
然后打开VS的服务器资源管理器,刷新数据连接,将LinqTest数据库中的Person表托至Linq To sql类文件中,然后点击生成菜单里的生成解决方案,结果如图所示:
在这里大家要注意一点,凡是拖入Linq To sql类文件中的数据表,必须设置主键,如果这里没有设置主键,在使用的LinqToSqlDataContext时会报错的。
下边是涉及到具体的操作,我会一步一步我这几项操作给大家讲解一下。
首先在Form1.cs代码页先示例话一个全局的LinqToSqlDataContext对象,如下:
//LinqToSqlDataContext也就是我们通常所说的数据上下文,我们新建Linq To Sql类文件时,会自动生成这个数据上下文,相当于我们通常用的DataContext类,该类的构造函数有三种形式,这里采用的是构造参数为连接字符串,这种构造比较简单实用
LinqToSqlDataContext ltsDataContext = new LinqToSqlDataContext("database=.;Integrated Security=true;Initial Catalog=LinqTest");
下面开始具体的操作:
一、添加
我们在添加按钮的Click事件执行方法里,写下如下代码:
private void btnadd_Click(object sender, EventArgs e)
{
try
{
ltsDataContext.GetTable<Pserson>().InsertAllOnSubmit(
new LINQTOSQL.App_Data.Pserson[2]{
new Pserson(){ PName="Mo", PSex="男", PJob="摄影师",PAge=23},
new Pserson(){ PName="Yao", PAge=23,PSex="女", PJob="作家"}});
MessageBox.Show("一次添加了两条信息");
ltsDataContext.Pserson.InsertOnSubmit(new Pserson()
{
PName = txtname.Text,
PAge = Convert.ToInt32(txtage.Text),
PJob = txtjob.Text,
PSex = txtsex.Text
});
ltsDataContext.SubmitChanges();
dataGridView1.DataSource = ltsDataContext.Pserson.Where(p => p.PName == txtname.Text);
MessageBox.Show("恭喜您,信息添加成功!");
}
catch
{
MessageBox.Show("添加信息失败!请重新添加!");
}
}
结果:
一下子插入了三条数据,ltsDataContext.InsertAllOnSubmit()插入2条数据,ltsDataContext.InsertOnSubmit()插入1条数据。
在实现添加的功能里,主要使用了ltsDataContext.InsertAllOnSubmit()函数、ltsDataContext.InsertOnSubmit()函数和ltsDataContext.SubmitChanges()函数,还有一个ltsDataContext.Get<T>()函数,该函数主要返回T类型的对象集合这里和ltsDataContext.T是等效的。
InsertOnSubmit()函数,主要用于将数据实体添加到Table<Person>表集合中,该函数的参数为Person对象,也就是我们在文本框中输入的人员信息,经过封装后的实体。
此外还有一个添加信息的函数为InsertAllOnSubmit()函数,看到该该函数名我想大家已经猜到了,这个函数添加的是一个IEnumerable<Person>的对象,也就是相当于一次添加多个Person对象的操作。在上边的示例中高亮的部分即是。
下面讲添加操作中用到的第二个函数,SubmitChanges(),由函数名即可猜到,该函数是用来提交保存变更的信息的。除了默认的无参调用之外,该函数还有一个重载,该重载的参数为ConflictMode类型的枚举值,该类型有两个值分别为:
ContinueOnConflict:尝试对数据库的所有更新,在更新结束后累计返回并发冲突
FailOnFirstConflict:在检测到第一数据并发冲突错误时,就立即停止尝试更新数据库的操作
通过解释这两个不同的值我想大家已经明白该如何去使用了,在后边还会大量的用到SubmitChanges()这个函数,后边就不再介绍了。
二、查找
因为这个示例本身只是一个演示的demo,所以没有做过多的处理,这里只是做了基本异常处理,还有这里的查找只能通过姓名查找,多条件查找,希望朋友们在下边自己练习吧,道理都是一样的。
好的,请看下面的示例,在查找按钮CLick事件的执行方法里添加如下代码:
private void btnserach_Click(object sender, EventArgs e)
{
try
{ //这里仅实现了按姓名查询,如果多添加查询可以在where里用与的方式加查询条件
var persons = ltsDataContext.Pserson.Where(p => p.PName == txtname.Text);
dataGridView1.DataSource = persons;
LINQTOSQL.App_Data.Pserson person = (LINQTOSQL.App_Data.Pserson)persons.First();
txtage.Text = person.PAge.ToString();
txtjob.Text = person.PJob;
txtsex.Text = person.PSex;
}
catch
{
MessageBox.Show("查询异常,请确认输入无误后再查!");
}
}
结果:
这里主要是使用了ltsDataContext.Person.Where()方法来查询所要查找的对象,Where方法是一个扩展方法,该函数的参数是一个lambda表达式(相当于一个Func<,>的委托),通过该表达式可以找到名字和Name文本框中输入的名字相等的信息,然后再进行一下强制转换,并将相应的对象的属性赋值给相应的文本框,并在DataGridView中显示出来。
三、修改
先要输入所要修改的学生的姓名进行查找,查找之后相应的信息会显示在对应的文本框中,只需在对应的文本框中进行修改即可,最后再进行保存。
在修改按钮中代码如下:
private void btnchange_Click(object sender, EventArgs e)
{
LINQTOSQL.App_Data.Pserson person = ltsDataContext.Pserson.Where(p => p.PName == txtname.Text).OrderBy(p => p.PID).FirstOrDefault();
person.PName = txtname.Text;
person.PAge = Convert.ToInt32(txtage.Text);
person.PJob = txtjob.Text;
person.PSex = txtsex.Text;
ltsDataContext.SubmitChanges();
MessageBox.Show("信息更新成功!");
}
结果:
更新前
更新后
在更新操作里,所要涉及的知识点在前边都有讲过,这里就不在多讲了,需要注意的一点是,获取到所要查找的对象之后,直接在对对象的属性进行重新赋值更新即可。最后不要忘了进行提交保存。
四、删除
输入要删除的姓名即可。
删除按钮CLick事件执行代码:
private void btndelete_Click(object sender, EventArgs e)
{
ltsDataContext.GetTable<LINQTOSQL.App_Data.Pserson>().DeleteOnSubmit(ltsDataContext.Pserson.Where(p => p.PName == txtname.Text).FirstOrDefault());
ltsDataContext.SubmitChanges();
}
结果:
删除前:
删除后:
前后对比可知,姓名为“哈”的信息被删除了。
这里主要用到了ltsDataContext.DeleteOnSubmit()函数,该函数的参数是是Person对象,即要删除的Name为“哈”Person示例对象,在上边的示例用用的ltsDataContext.Person.Where()函数,这个在上边有介绍这里就不在讲了。
五、浏览
浏览既是浏览数据库里的所有数据,不需要任何的查询条件。
在浏览按钮Click事件的执行方法里代码如下:
private void btnscan_Click(object sender, EventArgs e)
{
try
{
//获取全部的数据
dataGridView1.DataSource = ltsDataContext.Pserson.GetNewBindingList();
}
catch
{
MessageBox.Show("浏览异常!");
}
}
结果:
在这里主要用到了ltsDataContext.Pserson.GetNewBindingList();该函数的功能是提供支持绑定到数据源所需的功能。即可以将数据库中的所有数据作为数据源。
六、执行SQL、
该示例主要是教大家在ltsDataContext中执行sql语句(存储过程),同时主要讲解下DataContex.Refresh()方法。
先看下执行SQL按钮下Click事件的执行方法
private void button1_Click(object sender, EventArgs e)
{
LINQTOSQL.App_Data.Pserson person = ltsDataContext.GetTable<LINQTOSQL.App_Data.Pserson>().Where(p => p.PName == txtname.Text).FirstOrDefault();
SqlConnection sqlConnection = new SqlConnection("database=.;Integrated Security=true;Initial Catalog=LinqTest");
sqlConnection.Open();
SqlCommand sqlcmd = sqlConnection.CreateCommand();
sqlcmd.CommandType = CommandType.Text;
sqlcmd.CommandText = "update Pserson set PAge='"+txtage.Text+"',PSex='"+txtsex.Text+"',PJob='"+txtjob.Text+"' where PName='" + txtname.Text + "'";
sqlcmd.ExecuteNonQuery();
sqlConnection.Close();
ltsDataContext.Refresh(RefreshMode.OverwriteCurrentValues, person);
MessageBox.Show("信息更新成功!");
}
结果:
更新前:
更新后:
DataContext.Refresh()方法由其名字可知其为刷新函数,该函数有两个参数,第一参数为RefreshMode.类型的枚举值,该枚举类型有是三个值
RefreshMode.OverwriteCurrentValues:用数据库中的值重写所有当前值
RefreshMode.KeepChanges:保留已更改的当前值,但将其他值更新为数据库的值
RefreshMode.KeepCurrentValues:用从数据库中检索的值替换原始值,不会修改当前值,待下次运行时会显示最新的更新值
好了,通过这个示例基本上把Linq To Sql要讲的东西基本上都讲完了,同时Linq学习心得分享这个系列到这里已经结束了,在总结、学习的过程中,我也真心的学到了很多东西,也很乐意把自己的所学和大家分享,也希望大家能有所得、有所获,还请大家多多指教。