快捷搜索:

LINQ入门教程(四)

1LINQ TO SQL(代码下载)

我们以一个酒店治理系统的数据库为例子

表布局很简单:GuestInfo(客人信息表),Room(房间表),RoomType(房间类型表),HotelInfo(每个月盈利信息)

整体便是,Room中有个房间类型ID的外键,客人表中有个房间的ID的外键。月盈利信息先不管

筹备:新建项目 linq_Ch4节制台法度榜样,新建DB文件夹

右击DB文件夹,添加→新建项

选择LINQ to SQL类,文件名为 Hotel.dbml,添加

打创办事器资本治理器,我的快捷键是Ctrl+W+L

选中这四张表,往已经打开的Hotel.dbml文件中拖放,然后Ctrl+S保存

1.1 查询单表

引入命名空间,让我们可以造访dbml文件

我们有个工具叫dbml文件名+DataContext组成的一个名称的工具,经由过程它你就可以操作数据库了

①查出空房间,还可以住两小我以上的房间的信息;查出的结果先按照 最大年夜住人数降序显示结果再按照床位数降序显示结果(熬炼基础单表查询,多前提排序)

代码如下:

1:HotelDataContext db = new HotelDataContext();

2://2013年4月6日8:04:06 茗洋芳竹3://1. 查出空房间,还可以住两小我以上的房间的信息;查出的结果先按照 最大年夜住人数降序显示结果,再按照床位数降序显示结果

4:var query1 = from o in db.Room5:where o.R_Status == 0 && o.R_MaxPNum > 1

6:orderby o.R_MaxPNum descending,o.R_BedNum descending7:select o;

8:9:foreach (var item in query1)

10:{11:Console.WriteLine(string.Format("房间ID:{0}\t{1}\t床位数:{2},最多可住{3}人,描述:{4}",item.R_ID,item.R_Status==0?"余暇":"有人",item.R_BedNum,item.R_MaxPNum,item.R_Discription));

12:}

效果图:

1.2 嵌套要领查询

①按房间类型查询出房间的信息

效果图:

代码如下:

1://2.按房间类型查询出房间的信息

2:var query2 = from b in db.RoomType3:select new

4:{5:RoomTypeName = b.RT_Name,

6:RoomPrice = b.RT_Price,7:Items = from c in db.Room

8:where c.R_RT_ID == b.RT_ID9:select c

10:};11:

12:foreach (var item in query2)13:{

14:Console.WriteLine();15:Console.WriteLine("房间类型:" + item.RoomTypeName + ",价格是" + Math.Round(item.RoomPrice, 2).ToString());

16:if (item.Items.Count() > 0)17:{

18:foreach (var r_info in item.Items)19:{

20:Console.WriteLine(string.Format("{0}({1}):{2}", r_info.R_ID, r_info.R_Status == 0 ? "余暇" : "有人", r_info.R_Discription));21:}

22:}23:else

24:{25:Console.WriteLine("该类型下没有任何房间!");

26:}27:}

类似的sql语句赞助你理解:

select a.RT_Name,(select top 1 R_ID from dbo.Room b where a.RT_ID=b.R_RT_ID) as RID from dbo.RoomType a

1.3 多表联合查询

①查出客人的信息,房间的类型信息

1:var query3 = from r in db.Room

2:join guest in db.GuestInfo on r.R_ID equals guest.G_R_ID3:join rt in db.RoomType on r.R_RT_ID equals rt.RT_ID

4:select new5:{

6:personID = guest.G_ID,7:personName = guest.G_Name,

8:personCardId = guest.G_CardId,9:roomTName = rt.RT_Name,

10:roomStatus = r.R_Status,11:personStatus=guest.G_Status,//结账状态

12:};13:

14:foreach (var info in query3)15:{

16:Console.WriteLine(string.Format("{0}:{1},身份证:{2},房间类型名称:{3},结账状态:{5},房间状态:{4}", info.personID, info.personName, info.personCardId, info.roomTName, info.roomStatus == 0 ? "余暇" : "有人", info.personStatus == 0 ? "未结账" : "已结账"));17:}

效果图:

1.4 group多个前提分组

①查出客户信息,按照房间号,结账状态分组,统计每种状态的押金数和已收入的钱财数

为了测试真实性,我又添加了一些数据,表中数据如下:

统计查询效果图:

代码如下:

1://4.按照房间号,结账状态分组,房间号第一前提,状态第二前提,结算已收入的押金数和收入数信息

2:var query4 = from a in db.GuestInfo3:group a by new { a.G_R_ID, a.G_Status } into g//按照房间号和客人结账状态分组

4:select new5:{

6:房间号 = g.Key.G_R_ID,7:房间结账状态 = g.Key.G_Status == 0 ? "未结账" : "已结账",

8:押金数 = g.Sum(i => i.G_Deposit),9:收入数 = g.Sum(i => i.G_Pay),

10:统计数=g.Count()11:};

12:13:foreach (var item in query4)

14:{15:Console.WriteLine(string.Format("房间号(统计了{4}间):{0}\t结账状态:{1}\t押金数:{2}\t收入数:{3}", item.房间号, item.房间结账状态, item.押金数, item.收入数, item.统计数));

16:}

阐明:

LINQ查询表达式的语法既不能吸收group子句中的,也不容许一个查询中包孕多个group子句

下面两种写法是差错的:

应用LINQ to SQL进行数据分组查询时效率会有必然的丧掉。由于LINQ语句终极会被解释为SQL语句履行,然则LINQ语句解释为SQL时会有必然的效率丧掉,可以应用视图等数据库工具构建高效的数据查询。

1.5 前提要领查询

①用Where

代码如下:

//5.前提查询

var query5_1 = db.GuestInfo.Where(p => p.G_Name == "周恩来");foreach (var item in query5_1)

{Console.WriteLine(item.G_Name+"在"+item.G_RentDate.ToString("yyyy年MM月dd日 hh点mm分")+"入住我旅店");

}

②Enumerable类的Where措施如下所示:

public static IEnumerable Where(this IEnumerable source,Func predicate)

此中predicate,用于测试每个元素是否满意前提的一个函数。Where操作符吸收的参数类型为Func。该类型是具有一个参数并返回布尔值的委托。

接下来,我们来改写一下Where,自定义一个查询措施,叫ConditionQuery

public static IEnumerable ConditionQuery(IEnumerable source, Funcbool> predicate)

{return source.Where(predicate);

}

应用如下:

1://自定义查询,替代where

2:var query5_2 = ConditionQuery(db.GuestInfo,item=>item.G_Name=="周恩来");3:Console.WriteLine("第二种要领");

4:foreach (var item in query5_2)5:{

6:Console.WriteLine(item.G_Name + "在" + item.G_RentDate.ToString("yyyy年MM月dd日 hh点mm分") + "入住我旅店");7:}

效果图:

阐明:

LINQ to SQL中应用where自居筛选数据时,效率较高。基础上所有LINQ to SQL查询中含有的where自居都邑被解释为SQL语句中的where子句部分。

1.6 类似于数据库中的Not Exists的语句

查出一次都没有租出去的屋子的信息,contains措施加上!号,效果等同于not exists

1://6.查出一次都没有租出去的屋子的信息

2:var query6 = from r in db.Room3:where !(from g in db.GuestInfo

4:select g.G_R_ID5:).Contains(r.R_ID)

6:select new7:{

8:房间编号 = r.R_ID,9:房间阐明 = r.R_Discription,

10:床位数 = r.R_BedNum,11:最多可住人数 = r.R_MaxPNum

12:};13:

14:foreach (var item in query6)15:{

16:Console.WriteLine(string.Format("房间编号:{0};床位数:{1};最多可住人数:{2};房间阐明:{3}",item.房间编号,item.床位数,item.最多可住人数,item.房间阐明));17:}

效果图如下:

1.7 分组联接 GroupJoin

表A.GroupJoin(表B,表A外键,表B外键,处置惩罚措施)

表A中数据全显示,表B关联上的就显示,否则为空,类似于左查询

代码如下:

1://7.分组联接 GroupJoin

2:var query7 = db.Room.GroupJoin(3:db.GuestInfo,

4:m => m.R_ID,5:n => n.G_R_ID,

6:(m, n) => new7:{

8:房间ID=m.R_ID,9:房间状态 = m.R_Status == 0 ? "余暇" : "有人",

10:已经为您盈利=n.Sum(k=>k.G_Pay)11:}

12:);13:foreach (var item in query7)

14:{15:Console.WriteLine(string.Format("房间编号:{0};\t{1}\t已经为您盈利{2:C}", item.房间ID, item.房间状态, item.已经为您盈利));

16:}

效果图:

1.8 聚合操作系列(常用于分组后处置惩罚,比较用法可参考1.4例子)

①Count操作:统计次数,例子很简单不写了

②LongCount操作:跟Count一样,便是返回值是Int64类型的

③Sum操作:统计总额,累计

④Max操作:取一组值中的最大年夜值

⑤Min操作:取一组值中的最小值

⑥Average操作:取一组值中的匀称值

⑦Aggregate操作:用于对聚拢中的元素进行自定义的聚同谋略

例如:统计今年的总盈利额,我们操作HotelInfo表

效果图:

代码如下:

1://8. Aggregate操作例子

2:decimal[] amountArray = db.HotelInfo.Select(item => item.earnMoney).ToArraydecimal>();3:double amountSum=Convert.ToDouble(amountArray.Aggregate((a, b) =>a+b));

4:Console.WriteLine("一共" + amountSum+"元");

等同于:

decimal amountSum = db.HotelInfo.Sum(item=>item.earnMoney);

1.9 应用视图查询

筹备事情:打开Hotel.dbml文件,打创办事器资本治理器,将视图文件夹的视图拖放到dbml文件中

V_SelectRoom只是查询Room和RoomType的一个视图,我们操作的时刻把它当做一张表去处置惩罚就行了。

代码如下:

1:var query9 = from vi in db.V_SelectRoom

2:join g in db.GuestInfo3:on vi.R_ID equals g.G_R_ID

4:where g.G_Status==05:select new

6:{7:房间ID = vi.R_ID,

8:客人姓名 = g.G_Name9:};

10:foreach (var item in query9)11:{

12:Console.WriteLine(item.房间ID+""+item.客人姓名);13:}

效果图:

主要阐明的意思是:

应用视图筛选数据,可以极大年夜的前进LINQ to SQL履行查询效率。应用LINQ to SQL查询多表数据时,会带来必然的效率确凿,以是先把繁杂数据筛选编译为视图,应用LINQ to SQL直接查询视图数据可显明前进数据查询效率。

2.1 应用存储历程查询

筹备事情:打开Hotel.dbml文件,打创办事器资本治理器,将存储历程文件夹下的sp_select_roomByRT拖放到dbml文件中,该存储历程是根据房间类型ID得到房间信息

拖放后,在dbml文件右侧

ALTER proc [dbo].[sp_select_roomByRT]

@RT int as

select R_BedNum,R_ID,R_MaxPNum,R_Status=case when R_Status=1 then '有人' else '余暇' end,R_Discription,R_Count from Room where R_RT_ID=@RT

应用如下,也异常简单:

1://10.应用存储历程查询

2:var query10 = db.sp_select_roomByRT(1);3:foreach (var item in query10)

4:{5:Console.WriteLine(string.Format("房间编号:{0},房间状态:{1},房间描述:{2}", item.R_ID,item.R_Status,item.R_Discription));

6:}

效果图:

主要阐明的意思是:

进行繁杂的数据统计、查询、多表联合查询时,可以应用存储历程封装繁杂查询来简化LINQ to SQL类的操作,从而前进数据操作效率。当应用DataContext工具的存储历程天生的措施查询数据时,所稀有据都邑被存储至ISingleResult泛型聚拢中。

2.2 应用存储历程操作

筹备事情:打开Hotel.dbml文件,打创办事器资本治理器,将存储历程文件夹下的sp_Insert_Room拖放到dbml文件中,该存储历程是创建一个新居间

拖放后,在dbml文件右侧

ALTER proc sp_Insert_Room

@R_RT_ID int,@R_Discription varchar(50),

@R_bedNum int,@R_MaxPNum int

as begin

insert Room(R_RT_ID,R_Discription,R_BedNum,R_MaxPNum) values(@R_RT_ID,@R_Discription,@R_bedNum,@R_MaxPNum)end

应用如下,也异常简单:

1:db.sp_Insert_Room(1, "这是一间于2013年4月7日0:33:43添加进去的新居间,床有9个,最多可住15小我", 9, 15);

2:Console.WriteLine("添加成功!");

效果图:

接下来我们将sp_Insert_RoomReturnInsertID存储历程也拖放到dbml文件中去

存储历程代码:

1:ALTER proc [dbo].[sp_Insert_RoomReturnInsertID]

2:@R_RT_ID int,3:@R_Discription varchar(50),

4:@R_bedNum int,5:@R_MaxPNum int

6:as 7:begin

8:insert Room(R_RT_ID,R_Discription,R_BedNum,R_MaxPNum) values(@R_RT_ID,@R_Discription,@R_bedNum,@R_MaxPNum)9:select @@identity;

0:end

代码如下:

1:var queryId= db.sp_Insert_RoomReturnInsertID(1, "这是一间于2013年4月7日0:33:43添加进去的新居间,床有9个,最多可住15小我", 9, 15);

2:foreach (var item in queryId)3:{

4:Console.WriteLine("添加成功!插入成功后的主键ID为"+item.Column1);5:}

效果图:

同理关于delete,update相关的存储历程操作,我就不写了。

转自:http://www.cnblogs.com/Fresh-Air/archive/2013/04/07/3001934.html

您可能还会对下面的文章感兴趣: