我们继续来学习LINQ to SQL的数据上下文datacontext
由于我们之前经常用,且在**.designer.cs我们可以很明白的看清其全部定义,我们在这里单独研究数据上下文是要研究其几个属性和方法:
对于其有些属性,个人感觉很多时候都用不到,这里只是提一下,用到的时候可以自己去查
1.连接属性Connection(可以获得DataContext类的实例的连接(类型为DbConnection))
2.事务属性Transaction(为DataContext类的实例设置访问数据库的事务)
3.执行命令的最大时间属性CommandTimeout(可以设置或获取DataContext类的实例的查询数据操作的超时期限,单位为妙,默认值是30妙)
4.冲突对象集合属性ChangeConflicts(返回DataContext类的实例调用SubmitChanges()方法时导致并发冲突的对象的集合)
5.是否延时加载关系属性DeferredLoadingEnabled(可以设置DataContext类的实例是否延时加载关系,有时为了减少用户的等待时间,可以将其设为false)
6.数据导入选项属性LoadOptions(可以设置或获取DataContext类的实例的DataLoadOptions类的实例,DataLoadOptions类提供了两种方法AssociateWith()和LoadWith())
那么DataLoadOptions类提供的AssociateWith()和LoadWith()是干什么的呢?我们以LoadWith()为例直接上代码:
protected void Button13_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
DataLoadOptions dlo = new DataLoadOptions(); 实例化DataLoadOptions类
下面一句代码意思是加载主表ComManager的同时也加载与主表中数据相关的Company表的数据(就是说这俩表要有外键关系)
dlo.LoadWith<ComManager>(cm => cm.Company);
通过LoadOptions属性将DataContext类的实例设置为DataLoadOptions类的实例
db.LoadOptions = dlo;
var commanagers = from cm in db.ComManager select cm;
foreach (var commanager in commanagers)
{
Label13.Text += "企业管理员:" + commanager.Name+"<br/>";
foreach (var company in commanager.Company)
{
Label13.Text += "企业名:" + company.CompanyName + "<br/>";
}
}
}
这里只是两个表相关,如果有多个表相关,你可以多写几个 dlo.LoadWith<主表>(u => u.副表);然后按顺序再多加几个foreach内循环。
7.日志属性Log(可以将DataContext类的实例的SQL查询或命令显示出来)
因为Log属性返回值类型为System.IO.TextWirter,所以可以用Response.Output(db.Log=Response.Output)
现在我们来学习DataContext类的几个方法
1.DatabaseExists()检测数据库是否存在,返回bool db.DatabaseExists()
2.CreateDatabase()创建数据库,无返回值 db.CreateDatabase()
3.DeleteDatabase()删除数据库,无返回值 db.DeleteDatabase()
以上3中方法具体使用代码就不写了,个人认为不是很实用
4.ExecuteCommand()执行SQL增删改命令,返回值是整数(影响的记录数)
protected void Button15_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
第一个参数注意语句中的参数的写法
string sql = "insert into leaveword (companyid, accounter, [content]) values ({0},{1},{2})";
int comid=int.Parse(TextBox7.Text);
string acc=TextBox8.Text;
string leaw=TextBox9.Text;
第二个参数是一个object数组
object[] param=new object[]{comid,acc,leaw};
ExecuteCommand中第一个参数是要执行的增删改语句,第二个参数是语句中的参数组成的object数组
int result = db.ExecuteCommand(sql, param);
Label14.Text = "有" + result.ToString() + "记录被影响";
}
5.ExecuteQuery<T>()执行SQL查询命令,返回值类型是我们熟悉的IEnumerable<T>泛型集合类型
由于使用了泛型,别忘了引入System.Collections.Generic
protected void Button16_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
使用跟ExecuteCommand()大同小异,不过要注意的是查询字段里一定要有主键(如本处的leavewordid)
string sql = "select top 3 leavewordid,accounter,content from leaveword where accounter={0}";
string acc = TextBox10.Text;
object[] param = new object[] { acc };
IEnumerable<LeaveWord> result = db.ExecuteQuery<LeaveWord>(sql, param);
foreach (var item in result)
{
Label15.Text += item.Accounter+ "<br/> "+ item.Content+"<br/>";
虽然有些字段也能敲出(如本处的Reply),但由于在查询语句里没有查它,所以显示的是该字段的类型的默认值
// Label15.Text += item.Accounter+ "<br/> "+ item.Reply+"<br/>";
}
}
6.SubmitChanges()提交更改到数据库,这个方法我们在EntitySet<T>里用过http://kendezhu.iteye.com/blog/792583
protected void Button17_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
LeaveWord lw = new LeaveWord();
lw.CompanyID = int.Parse(TextBox11.Text);
lw.Accounter = TextBox12.Text;
lw.Content = TextBox13.Text;
db.表属性(属性内部通过GetTable<T>方法获得表(记录集)),如本处返回类型是Table<LeaveWord>(就是LeaveWord表,所以表里的记录类型是LeaveWord类型),其继承了IEnumerable<T>接口,所以对于我们在http://kendezhu.iteye.com/blog/776538讲的查询操作其都能用,而且其还有一些自有的操作如下面的InsertOnSubmit()向记录集里添加记录,类似的还有DeleteOnSubmit()
db.LeaveWord.InsertOnSubmit(lw); 指定的转换无效 .net3.5的bug
db.SubmitChanges();
}
7.GetCommand()获取命令信息 DbCommand类须 using System.Data.Common;
protected void Button1_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
var result = from u in dc.Company where u.CompanyName == "桂林山水生态" select u.Employ;
DbCommand dbcommand = db.GetCommand(result);
Label1.Text = dbcommand.CommandText; SQL语句
Label2.Text = dbcommand.CommandType; 执行方式
Label3.Text = dbcommand.Connection; 数据库连接
}
protected void Button1_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
var result = db.Company.Where<Company>(u => u.CompanyName.Equals("桂林山水生态"));
DbCommand dbcommand = db.GetCommand(result);
Label1.Text = dbcommand.CommandText; SQL语句
Label2.Text = dbcommand.CommandType; 执行方式
Label3.Text = dbcommand.Connection; 数据库连接
}
GetCommand里面的参数类型必须为IQueryable<T>或IQueryable,而这种类型一般只有LINQ to SQL的查询表达式或查询操作返回,到了这时候我们也该总结一下LINQ的数据类型了,首先LINQ的数据类型分为等号左边的返回值的数据类型和等号右边的数据源的数据类型,不管右边是查询表式(http://kendezhu.iteye.com/admin/blogs/757044的注)还是查询操作(http://kendezhu.iteye.com/admin/blogs/776538)右边数据源(数组,Table<T>,List<T>等)的数据类型必须是直接或间接继承自IEnumerable<T>接口,而左边返回值的数据类型也直接或间接继承自IEnumerable<T>接口(如果返回的是集合类型的值,如果是其他类型(如部分查询操作)则另当别论),而一般等号左边返回值的类型我们可以不知道,直接写一个var就可以了。
补:
既然讲到了数据类型,突然想起了GridView等有DataSource属性的数据绑定控件,那么它们都能绑定什么样的数据类型的集合呢?通过实验(给其DataSource属性属性赋值整型1,呵呵,肯定会出错。看其出错页面),得出结论:能绑定继承自IListSource,IEnumerable,IDataSource接口的数据类型,除了Datatable继承自IListSource外还查到字符串类型继承自IEnumerable<char>等接口。
8.GetTable<T>()获取表(记录集)
在第6个方法中已经提到了这个方法,其效果与数据上下文的对应属性一样
protected void Button1_Click(object sender, EventArgs e)
{
linqtosqlDataContext db = new linqtosqlDataContext();
var result = db.Company;
var result = db.GetTable<Company>();
上面的两句代码是等同的,左右边的类型都是Table<Company>类型
foreach(var item in result)
{
}
}
9.GetChangeSet()获取已被增删改的对象,返回值类型为ChangeSet(该类有三个属性(Insetrs,Deletes,Updates)分别返回已被增删改的实体的集合(集合类型是IList<Object>)
不过这个方法对使用ExecuteCommand()执行SQL增删改命令时修改的对象无法统计
ChangeSet set=db.GetChangeSet();
Label1.Text=set; 直接输出set,显示样式为{Inserts:数字,Deletes:数字,Updates:数字}
10.Translate()转换IDataReader对象...........................................................
11.Refresh()刷新对象状态