linq to sql学习笔记.docx
- 文档编号:9728399
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:58
- 大小:276.49KB
linq to sql学习笔记.docx
《linq to sql学习笔记.docx》由会员分享,可在线阅读,更多相关《linq to sql学习笔记.docx(58页珍藏版)》请在冰豆网上搜索。
linqtosql学习笔记
linqtosql
(一)
什么是Linqtosql
Linqtosql(或者叫DLINQ)是LINQ(.NET语言集成查询)的一部分,全称基于关系数据的.NET语言集成查询,用于以对象形式管理关系数据,并提供了丰富的查询功能,它和Linqtoxml、Linqtoobjects、Linqtodataset、Linqtoentities等组成了强大的LINQ。
要学好LINQ查询语法,就不得不先理解C#3.0的一些新特性,下面一一简单介绍。
隐含类型局部变量
varage=26;
varusername="zhuye";
varuserlist=new[]{"a","b","c"};
foreach(varuserinuserlist)
Console.WriteLine(user);
纯粹给懒人用的var关键字,告诉编译器(对于CLR来说,它是不会知道你是否使用了var,苦力是编译器出的),你自己推断它的类型吧,我不管了。
但是既然让编译器推断类型就必须声明的时候赋值,而且不能是null值。
注意,这只能用于局部变量,用于字段是不可以的。
匿名类型
vardata=new{username="zhuye",age=26};
Console.WriteLine("username:
{0}age:
{1}",data.username,data.age);
匿名类型允许开发人员定义行内类型,无须显式定义类型。
常和var配合使用,var用于声明匿名类型。
定义一个临时的匿名类型在LINQ查询句法中非常常见,我们可以很方便的实现对象的转换和投影。
扩展方法
publicstaticclasshelper
{
publicstaticstringMD5Hash(thisstrings)
{
returnSystem.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s,"MD5");
}
publicstaticboolIn(thisobjecto,IEnumerableb)
{
foreach(objectobjinb)
{
if(obj==o)
returntrue;
}
returnfalse;
}
}
//调用扩展方法
Console.WriteLine("123456".MD5Hash());
Console.WriteLine("1".In(new[]{"1","2","3"}));
很多时候我们需要对CLR类型进行一些操作,苦于无法扩展CLR类型的方法,只能创建一些helper方法,或者生成子类。
扩展方法使得这些需求得意实现,同时也是实现LINQ的基础。
定义扩展方法需要注意,只能在静态类中定义并且是静态方法,如果扩展方法名和原有方法名发生冲突,那么扩展方法将失效。
自动属性
publicclassPerson
{
publicstringusername{get;protectedset;}
publicintage{get;set;}
publicPerson()
{
this.username="zhuye";
}
}
Personp=newPerson();
//p.username="aa";
Console.WriteLine(p.username);
意义不是很大,纯粹解决机械劳动。
编译器自动为你生成get、set操作以及字段,并且你不能使用字段也不能自定义get、set操作,不过你可以分别定义get和set的访问级别。
对象初始化器
publicclassPerson
{
publicstringusername{get;set;}
publicintage{get;set;}
publicoverridestringToString()
{
returnstring.Format("username:
{0}age:
{1}",this.username,this.age);
}
}
Personp=newPerson(){username="zhuye",age=26};
Console.WriteLine(p.ToString());
编译器会自动为你做setter操作,使得原本几行的属性赋值操作能在一行中完成。
这里需要注意:
l 允许只给一部分属性赋值,包括internal访问级别
l 可以结合构造函数一起使用,并且构造函数初始化先于对象初始化器执行
集合初始化器
publicclassPerson
{
publicstringusername{get;set;}
publicintage{get;set;}
publicoverridestringToString()
{
returnstring.Format("username:
{0}age:
{1}",this.username,this.age);
}
}
varpersons=newList
newPerson{username="a",age=1},
newPerson{username="b",age=2}};
foreach(varpinpersons)
Console.WriteLine(p.ToString());
编译器会自动为你做集合插入操作。
如果你为Hashtable初始化的话就相当于使用了两个对象初始化器。
Lambda表达式
varlist=new[]{"aa","bb","ac"};
varresult=Array.FindAll(list,s=>(s.IndexOf("a")>-1));
foreach(varvinresult)
Console.WriteLine(v);
其实和2.0中的匿名方法差不多,都是用于产生内联方法,只不过Lambda表达式的语法更为简洁。
语法如下:
(参数列表)=>表达式或者语句块
其中:
参数个数:
可以有多个参数,一个参数,或者无参数。
表达式或者语句块:
这部分就是我们平常写函数的实现部分(函数体)。
前面的示例分别是1个参数的例子,下面结合扩展方法来一个复杂的例子:
publicdelegateintmydg(inta,intb);
publicstaticclassLambdaTest
{
publicstaticintoper(thisinta,intb,mydgdg)
{
returndg(a,b);
}
}
Console.WriteLine(1.oper(2,(a,b)=>a+b));
Console.WriteLine(2.oper(1,(a,b)=>a-b));
查询句法
varpersons=newList
newPerson{username="a",age=19},
newPerson{username="b",age=20},
newPerson{username="a",age=21},
};
varselectperson=frompinpersonswherep.age>=20selectp.username.ToUpper();
foreach(varpinselectperson)
Console.WriteLine(p);
查询句法是使用标准的LINQ查询运算符来表达查询时一个方便的声明式简化写法。
该句法能在代码里表达查询时增进可读性和简洁性,读起来容易,也容易让人写对。
VisualStudio对查询句法提供了完整的智能感应和编译时检查支持。
编译器在底层把查询句法的表达式翻译成明确的方法调用代码,代码通过新的扩展方法和Lambda表达式语言特性来实现。
上面的查询句法等价于下面的代码:
varselectperson=persons.Where(p=>p.age>=20).Select(p=>p.username.ToUpper());
LINQ查询句法可以实现90%以上T-SQL的功能(由于T-SQL是基于二维表的,所以LINQ的查询语法会比T-SQL更简单和灵活),但是由于智能感应的原因,select不能放在一开始就输入。
Linqtosql
(二):
DataContext与实体
DataContext
DataContext类型(数据上下文)是System.Data.Linq命名空间下的重要类型,用于把查询句法翻译成SQL语句,以及把数据从数据库返回给调用方和把实体的修改写入数据库。
DataContext提供了以下一些使用的功能:
以日志形式记录DataContext生成的SQL
执行SQL(包括查询和更新语句)
创建和删除数据库
DataContext是实体和数据库之间的桥梁,那么首先我们需要定义映射到数据表的实体。
定义实体类
usingSystem.Data.Linq.Mapping;
[Table(Name="Customers")]
publicclassCustomer
{
[Column(IsPrimaryKey=true)]
publicstringCustomerID{get;set;}
[Column(Name="ContactName")]
publicstringName{get;set;}
[Column]
publicstringCity{get;set;}
}
以Northwind数据库为例,上述Customers类被映射成一个表,对应数据库中的Customers表。
然后在类型中定义了三个属性,对应表中的三个字段。
其中,CustomerID字段是主键,如果没有指定Column特性的Name属性,那么系统会把属性名作为数据表的字段名,也就是说实体类的属性名就需要和数据表中的字段名一致。
现在,创建一个ASP.NET页面,然后在页面上加入一个GridView控件,使用下面的代码进行绑定数据:
usingSystem.Data.Linq;
DataContextctx=newDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
Table
GridView1.DataSource=fromcinCustomerswherec.CustomerID.StartsWith("A")selectnew{顾客ID=c.CustomerID,顾客名=c.Name,城市=c.City};
GridView1.DataBind();
使用DataContext类型把实体类和数据库中的数据进行关联。
你可以直接在DataContext的构造方法中定义连接字符串,也可以使用IDbConnection:
usingSystem.Data.SqlClient;
IDbConnectionconn=newSqlConnection("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
DataContextctx=newDataContext(conn);
之后,通过GetTable获取表示底层数据表的Table类型,显然,数据库中的Customers表的实体是Customer类型。
随后的查询句法,即使你不懂SQL应该也能看明白。
从Customers表中找出CustomerID以“A”开头的记录,并把CustomersID、Name以及City封装成新的匿名类型进行返回。
结果如下图:
强类型DataContext
publicpartialclassNorthwindDataContext:
DataContext
{
publicTable
publicNorthwindDataContext(IDbConnectionconnection):
base(connection){}
publicNorthwindDataContext(stringconnection):
base(connection){}
}
强类型数据上下文使代码更简洁:
NorthwindDataContextctx=newNorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
GridView1.DataSource=fromcinctx.Customerswherec.CustomerID.StartsWith("A")selectnew{顾客ID=c.CustomerID,顾客名=c.Name,城市=c.City};
GridView1.DataBind();
DataContext其实封装了很多实用的功能,下面一一介绍。
日志功能
usingSystem.IO;
NorthwindDataContextctx=newNorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
StreamWritersw=newStreamWriter(Server.MapPath("log.txt"),true);//Append
ctx.Log=sw;
GridView1.DataSource=fromcinctx.Customerswherec.CustomerID.StartsWith("A")selectnew{顾客ID=c.CustomerID,顾客名=c.Name,城市=c.City};
GridView1.DataBind();
sw.Close();
运行程序后在网站所在目录生成了log.txt,每次查询都会把诸如下面的日志追加到文本文件中:
SELECT[t0].[CustomerID],[t0].[ContactName],[t0].[City]
FROM[Customers]AS[t0]
WHERE[t0].[CustomerID]LIKE@p0
--@p0:
InputString(Size=2;Prec=0;Scale=0)[A%]
--Context:
SqlProvider(Sql2005)Model:
AttributedMetaModelBuild:
3.5.20706.1
应该说这样的日志对于调试程序是非常有帮助的。
探究查询
usingSystem.Data.Common;
usingSystem.Collections.Generic;
NorthwindDataContextctx=newNorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
varselect=fromcinctx.Customerswherec.CustomerID.StartsWith("A")selectnew{顾客ID=c.CustomerID,顾客名=c.Name,城市=c.City};
DbCommandcmd=ctx.GetCommand(select);
Response.Write(cmd.CommandText+"
");
foreach(DbParameterparmincmd.Parameters)
Response.Write(string.Format("参数名:
{0},参数值:
{1}
",parm.ParameterName,parm.Value));
Customercustomer=ctx.Customers.First();
customer.Name="zhuye";
IList
Response.Write(((Customer)queryText[0]).Name);
在这里,我们通过DataContext的GetCommand方法获取了查询对应的DbCommand,并且输出了CommandText和所有的DbParameter。
之后,我们又通过GetChangeSet方法获取了修改后的实体,并输出了修改内容。
执行查询
NorthwindDataContextctx=newNorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
stringnewcity="Shanghai";
ctx.ExecuteCommand("updateCustomerssetCity={0}whereCustomerIDlike'A%'",newcity);
IEnumerable
GridView1.DataSource=customers;
GridView1.DataBind();
前一篇文章已经说了,虽然Linqtosql能实现90%以上的TSQL功能。
但是不可否认,对于复杂的查询,使用TSQL能获得更好的效率。
因此,DataContext类型也提供了执行SQL语句的能力。
代码的执行结果如下图:
创建数据库
testContextctx=newtestContext("server=xxx;database=testdb;uid=xxx;pwd=xxx");
ctx.CreateDatabase();
[Table(Name="test")]
publicclasstest
{
[Column(IsPrimaryKey=true,IsDbGenerated=true)]
publicintID{get;set;}
[Column(DbType="varchar(20)")]
publicstringName{get;set;}
}
publicpartialclasstestContext:
DataContext
{
publicTable
publictestContext(stringconnection):
base(connection){}
}
这段代码在数据库中创建了名为testdb的数据库,等同于下面的脚本:
CREATETABLE[dbo].[test](
[ID][int]IDENTITY(1,1)NOTNULL,
[Name][varchar](20)COLLATEChinese_PRC_CI_ASNULL,
CONSTRAINT[PK_test]PRIMARYKEYCLUSTERED
(
[ID]ASC
)WITH(IGNORE_DUP_KEY=OFF)ON[PRIMARY]
)ON[PRIMARY]
同时,DataContext还提供了DeleteDatabase()方法,在这里就不列举了。
使用DbDataReader数据源
usingSystem.Data.SqlClient;
varconn=newSqlConnection("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
varctx=newDataContext(conn);
varcmd=newSqlCommand("select*fromcustomerswhereCustomerIDlike'A%'",conn);
conn.Open();
varreader=cmd.ExecuteReader();
GridView1.DataSource=ctx.Translate
GridView1.DataBind();
conn.Close();
你同样可以选择使用DataReader获取数据,增加了灵活性的同时也增加了性能。
看到这里,你可能会觉得手工定义和数据库中表对应的实体类很麻烦,不用担心,VS2008提供了自动生成实体类以及关系的工具,工具的使用将在以后讲解。
今天就讲到这里,和DataContext相关的事务、加载选项、并发选项以及关系实体等高级内容也将在以后讲解。
Linqtosql(三):
增删改
示例数据库
字段名
字段类型
允许空
字段说明
ID
uniqueidentifier
表主键字段
UserName
varchar(50)
留言用户名
PostTime
datetime
留言时间
Message
varchar(400)
√
留言内容
IsReplied
bit
留言是否回复
Reply
varchar(400)
√
留言管理员回复
在数据库中创建一个名为GuestBook的数据库,在里面创建一个tbGuestBook的表,结构如上表。
生成实体类
右键点击网站项目,选择添加新项,然后选择“LinqtosqlClasses”,命名为GuestBook。
然后打开App_Code里面的GuestBook.dbml。
设计视图上的文字提示你可以从服务器资源管理器或者
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linq to sql学习笔记 sql 学习 笔记