sg = (from g in dc.sgroup join gu in dc.sgroupuser on g.gKey equals gu.gKey into l from lgu in l.DefaultIfEmpty() select new { g, lgu }).ToList();
Lambda表达式如下:
var sg = dc.sgroup.GroupJoin(dc.sgroupuser, g => g.gKey, gu => gu.gKey, (g, gu) => new { g, gu }).Select(o=>o).ToList() ;
注意:
Linq 与Lambda表达式取出的结果有所不同.Linq取出的结果的记录数与Sql中的Left Join的结果相同,而Lambda表达式取出的记录数是sgroup表中的记录数,sgroupuser对应的记录是以对象集合存在于结果中
附:
下面是Inner Join:
Linq语法如下:
var sg = (from g in dc.sgroup join gu in dc.sgroupuser on g.gKey equals gu.gKey select new { g, gu }).ToList();
Lambda表达式如下:
var sg = dc.sgroup.Join(dc.sgroupuser, g => g.gKey, gu => gu.gKey, (g, gu) => new { g, gu }).Select(o=>o).ToList() ;
注意:
上面最后都用到了ToList()方法 , 用ToList()是为了一次性将数据取到本地.
Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
标签:
小编还为您整理了以下内容,可能对您也有帮助:
c# linq to sql中,没有看见左连接的关键字,请问是如何左连接,又连接,和内连接的呢?
左连接left outer join,除了满足连接条件的行,还包括左表的所有行。
右连接right outer join,除了满足连接条件的行,还包括右表的所有行。
eg:var q =
from e in db.Employees
join o in db.Orders on e equals o.Employee into ords
select new
{
e.FirstName,
e.LastName,
Order = ords
};
说明:以Employees 左表,Orders右表,Orders 表中为空时,用null值填充。Join的结果重命名 ords,Order是一个集合。
虽然没有left关键字,但是实现的查询结果是一样的。
linq用lambda表达式 left join 自连接怎么写
.问题解决
通过以上分析,将''改为NULL,问题得到有效解决或者把谓词写到每个子SQL里面。当然,只要是非''的都是可以的,比如' '(空格)。
dingjun123@ORADB> SELECT *
2 FROM (SELECT t1.subobject_name, t1.object_name, t1.object_type
3 FROM t1
4 UNION ALL
5 SELECT NULL, t2.object_name, t2.object_type
6 FROM t2
7 UNION ALL
8 SELECT t3.subobject_name, NULL, t3.object_type FROM t3) t
9 WHERE (t.subobject_name = 'T' OR t.object_name = 'T');
256 rows selected.
Elapsed: 00:00:00.72
Execution Plan
----------------------------------------------------------
Plan hash value: 3324794093
---------------------------------------------------------------------
linq用lambda表达式 left join 自连接怎么写
.问题解决
通过以上分析,将''改为NULL,问题得到有效解决或者把谓词写到每个子SQL里面。当然,只要是非''的都是可以的,比如' '(空格)。
dingjun123@ORADB> SELECT *
2 FROM (SELECT t1.subobject_name, t1.object_name, t1.object_type
3 FROM t1
4 UNION ALL
5 SELECT NULL, t2.object_name, t2.object_type
6 FROM t2
7 UNION ALL
8 SELECT t3.subobject_name, NULL, t3.object_type FROM t3) t
9 WHERE (t.subobject_name = 'T' OR t.object_name = 'T');
256 rows selected.
Elapsed: 00:00:00.72
Execution Plan
----------------------------------------------------------
Plan hash value: 3324794093
---------------------------------------------------------------------
linq to sql left join 三表以查询,该怎么解决
var q= from n in db.NewsModel
join b in db.BigClassModel on n.BigClassID equals b.BigClassID
join s in db.SmallClassModel on n.SmallClassID equals s.SmallClassID
orderby n.AddTime descending
select new
{
n.NewsID,
n.BigClassID,
n.SmallClassID,
n.Title,
b.BigClassName,
s.SmallClassName,
};
return q.ToList();
q.Count()//这个就是记录总数
linq 怎么写inner join
在读取Student表时inner join Class表取的对应的Class信息:
linq 怎么写inner join
在读取Student表时inner join Class表取的对应的Class信息:
什么是Lambda表达式?什么是 LINQ表达式?
//1 var ss = from r in db.Am_recProScheme select r; //2 var ss1 = db.Am_recProScheme; //3 string sssql = "select * from Am_recProScheme";
//1 var ss = from r in db.Am_recProScheme where r.rpId > 10 select r; //2 var ss1 = db.Am_recProScheme.Where(p => p.rpId > 10); //3 string sssql = "select * from Am_recProScheme where rpid>10";
//1 ////获取最大的rpId //var ss = (from r in db.Am_recProScheme // select r).Max(p => p.rpId); ////获取最小的rpId //var ss = (from r in db.Am_recProScheme // select r).Min(p => p.rpId); //获取结果集的总数 //var ss = (from r in db.Am_recProScheme // select r).Count(); //获取rpId的和 var ss = (from r in db.Am_recProScheme select r).Sum(p => p.rpId); //2 //var ss1 = db.Am_recProScheme.Max(p=>p.rpId); //var ss1 = db.Am_recProScheme.Min(p => p.rpId); //var ss1 = db.Am_recProScheme.Count() ; var ss1 = db.Am_recProScheme.Sum(p => p.rpId); Response.Write(ss); //3 string sssql = "select max(rpId) from Am_recProScheme"; sssql = "select min(rpId) from Am_recProScheme"; sssql = "select count(1) from Am_recProScheme"; sssql = "select sum(rpId) from Am_recProScheme";
var ss = from r in db.Am_recProScheme where r.rpId > 10 orderby r.rpId descending //倒序 // orderby r.rpId ascending //正序 select r; //正序 var ss1 = db.Am_recProScheme.OrderBy(p => p.rpId).Where(p => p.rpId > 10).ToList(); //倒序 var ss2 = db.Am_recProScheme.OrderByDescending(p => p.rpId).Where(p => p.rpId > 10).ToList(); string sssql = "select * from Am_recProScheme where rpid>10 order by rpId [desc|asc]";
//如果取最后一个可以按倒叙排列再取值 var ss = (from r in db.Am_recProScheme select r).FirstOrDefault(); //()linq to ef 好像不支持 Last() var ss1 = db.Am_recProScheme.FirstOrDefault(); //var ss1 = db.Am_recProScheme.First(); string sssql = "select top(1) * from Am_recProScheme";
//1 var ss = (from r in db.Am_recProScheme orderby r.rpId descending select r).Skip(10); //跳过前10条数据,取10条之后的所有数据 //2 var ss1 = db.Am_recProScheme.OrderByDescending(p => p.rpId).Skip(10).ToList(); //3 string sssql = "select * from (select ROW_NUMBER()over(order by rpId desc) as rowNum, * from [Am_recProScheme]) as t where rowNum>10";
//1 var ss = (from r in db.Am_recProScheme where r.rpId > 10 orderby r.rpId descending select r).Skip(10).Take(10); //取第11条到第20条数据 //2 Take(10): 数据从开始获取,获取指定数量(10)的连续数据 var ss1 = db.Am_recProScheme.OrderByDescending(p => p.rpId).Where(p => p.rpId > 10).Skip(10).Take(10).ToList(); //3 string sssql = "select * from (select ROW_NUMBER()over(order by rpId desc) as rowNum, * from [Am_recProScheme]) as t where rowNum>10 and rowNum<=20";
//1 var ss = from r in db.Am_recProScheme where r.SortsText.Contains("张") select r; //2 var ss1 = db.Am_recProScheme.Where(p => p.SortsText.Contains("张")).ToList(); //3 string sssql = "select * from Am_recProScheme where SortsText like ‘%张%‘";
//1 var ss = from r in db.Am_recProScheme orderby r.rpId descending group r by r.recType into n select new { n.Key, //这个Key是recType rpId = n.Sum(r => r.rpId), //组内rpId之和 MaxRpId = n.Max(r => r.rpId),//组内最大rpId MinRpId = n.Min(r => r.rpId), //组内最小rpId }; foreach (var t in ss) { Response.Write(t.Key + "--" + t.rpId + "--" + t.MaxRpId + "--" + t.MinRpId); } //2 var ss1 = from r in db.Am_recProScheme orderby r.rpId descending group r by r.recType into n select n; foreach (var t in ss1) { Response.Write(t.Key + "--" + t.Min(p => p.rpId)); } //3 var ss2 = db.Am_recProScheme.GroupBy(p => p.recType); foreach (var t in ss2) { Response.Write(t.Key + "--" + t.Min(p => p.rpId)); } //4 string sssql = "select recType,min(rpId),max(rpId),sum(rpId) from Am_recProScheme group by recType";
//1 var ss = from r in db.Am_recProScheme join w in db.Am_Test_Result on r.rpId equals w.rsId orderby r.rpId descending select r; //2 var ss1 = db.Am_recProScheme.Join(db.Am_Test_Result, p => p.rpId, r => r.rsId, (p, r) => p).OrderByDescending(p => p.rpId).ToList(); //3 string sssql = "select r.* from [Am_recProScheme] as r inner join [dbo].[Am_Test_Result] as t on r.[rpId] = t.[rsId] order by r.[rpId] desc";
//1 var ss = from p in db.Am_recProScheme where (new int?[] { 24, 25,26 }).Contains(p.rpId) select p; foreach (var p in ss) { Response.Write(p.Sorts); } //2 string st = "select * from Am_recProScheme where rpId in(24,25,26)";
Linq语法详细(三种方式:linq、Lambda、SQL语法)
标签:
什么是Lambda表达式?什么是 LINQ表达式?
//1 var ss = from r in db.Am_recProScheme select r; //2 var ss1 = db.Am_recProScheme; //3 string sssql = "select * from Am_recProScheme";
//1 var ss = from r in db.Am_recProScheme where r.rpId > 10 select r; //2 var ss1 = db.Am_recProScheme.Where(p => p.rpId > 10); //3 string sssql = "select * from Am_recProScheme where rpid>10";
//1 ////获取最大的rpId //var ss = (from r in db.Am_recProScheme // select r).Max(p => p.rpId); ////获取最小的rpId //var ss = (from r in db.Am_recProScheme // select r).Min(p => p.rpId); //获取结果集的总数 //var ss = (from r in db.Am_recProScheme // select r).Count(); //获取rpId的和 var ss = (from r in db.Am_recProScheme select r).Sum(p => p.rpId); //2 //var ss1 = db.Am_recProScheme.Max(p=>p.rpId); //var ss1 = db.Am_recProScheme.Min(p => p.rpId); //var ss1 = db.Am_recProScheme.Count() ; var ss1 = db.Am_recProScheme.Sum(p => p.rpId); Response.Write(ss); //3 string sssql = "select max(rpId) from Am_recProScheme"; sssql = "select min(rpId) from Am_recProScheme"; sssql = "select count(1) from Am_recProScheme"; sssql = "select sum(rpId) from Am_recProScheme";
var ss = from r in db.Am_recProScheme where r.rpId > 10 orderby r.rpId descending //倒序 // orderby r.rpId ascending //正序 select r; //正序 var ss1 = db.Am_recProScheme.OrderBy(p => p.rpId).Where(p => p.rpId > 10).ToList(); //倒序 var ss2 = db.Am_recProScheme.OrderByDescending(p => p.rpId).Where(p => p.rpId > 10).ToList(); string sssql = "select * from Am_recProScheme where rpid>10 order by rpId [desc|asc]";
//如果取最后一个可以按倒叙排列再取值 var ss = (from r in db.Am_recProScheme select r).FirstOrDefault(); //()linq to ef 好像不支持 Last() var ss1 = db.Am_recProScheme.FirstOrDefault(); //var ss1 = db.Am_recProScheme.First(); string sssql = "select top(1) * from Am_recProScheme";
//1 var ss = (from r in db.Am_recProScheme orderby r.rpId descending select r).Skip(10); //跳过前10条数据,取10条之后的所有数据 //2 var ss1 = db.Am_recProScheme.OrderByDescending(p => p.rpId).Skip(10).ToList(); //3 string sssql = "select * from (select ROW_NUMBER()over(order by rpId desc) as rowNum, * from [Am_recProScheme]) as t where rowNum>10";
//1 var ss = (from r in db.Am_recProScheme where r.rpId > 10 orderby r.rpId descending select r).Skip(10).Take(10); //取第11条到第20条数据 //2 Take(10): 数据从开始获取,获取指定数量(10)的连续数据 var ss1 = db.Am_recProScheme.OrderByDescending(p => p.rpId).Where(p => p.rpId > 10).Skip(10).Take(10).ToList(); //3 string sssql = "select * from (select ROW_NUMBER()over(order by rpId desc) as rowNum, * from [Am_recProScheme]) as t where rowNum>10 and rowNum<=20";
//1 var ss = from r in db.Am_recProScheme where r.SortsText.Contains("张") select r; //2 var ss1 = db.Am_recProScheme.Where(p => p.SortsText.Contains("张")).ToList(); //3 string sssql = "select * from Am_recProScheme where SortsText like ‘%张%‘";
//1 var ss = from r in db.Am_recProScheme orderby r.rpId descending group r by r.recType into n select new { n.Key, //这个Key是recType rpId = n.Sum(r => r.rpId), //组内rpId之和 MaxRpId = n.Max(r => r.rpId),//组内最大rpId MinRpId = n.Min(r => r.rpId), //组内最小rpId }; foreach (var t in ss) { Response.Write(t.Key + "--" + t.rpId + "--" + t.MaxRpId + "--" + t.MinRpId); } //2 var ss1 = from r in db.Am_recProScheme orderby r.rpId descending group r by r.recType into n select n; foreach (var t in ss1) { Response.Write(t.Key + "--" + t.Min(p => p.rpId)); } //3 var ss2 = db.Am_recProScheme.GroupBy(p => p.recType); foreach (var t in ss2) { Response.Write(t.Key + "--" + t.Min(p => p.rpId)); } //4 string sssql = "select recType,min(rpId),max(rpId),sum(rpId) from Am_recProScheme group by recType";
//1 var ss = from r in db.Am_recProScheme join w in db.Am_Test_Result on r.rpId equals w.rsId orderby r.rpId descending select r; //2 var ss1 = db.Am_recProScheme.Join(db.Am_Test_Result, p => p.rpId, r => r.rsId, (p, r) => p).OrderByDescending(p => p.rpId).ToList(); //3 string sssql = "select r.* from [Am_recProScheme] as r inner join [dbo].[Am_Test_Result] as t on r.[rpId] = t.[rsId] order by r.[rpId] desc";
//1 var ss = from p in db.Am_recProScheme where (new int?[] { 24, 25,26 }).Contains(p.rpId) select p; foreach (var p in ss) { Response.Write(p.Sorts); } //2 string st = "select * from Am_recProScheme where rpId in(24,25,26)";
Linq语法详细(三种方式:linq、Lambda、SQL语法)
标签:
left join 和 right jion 怎么表示 LINQ
left outer join=left join , right outer join=right join, inner join=join.
使用关系代数合并数据
1 关系代数
合并数据集合的理论基础是关系代数,它是由E.F.Codd于1970年提出的。
在关系代数的形式化语言中:
用表、或者数据集合表示关系或者实体。
用行表示元组。
用列表示属性。
关系代数包含以下8个关系运算符
选取――返回满足指定条件的行。
投影――从数据集合中返回指定的列。
笛卡尔积――是关系的乘法,它将分别来自两个数据集合中的行以所有可能的方式进行组合。
并――关系的加法和减法,它可以在行的方向上合并两个表中的数据,就像把一个表垒在另一个表之上一样。
交――返回两个数据集合所共有的行。
差――返回只属于一个数据集合的行。
连接――在水平方向上合并两个表,其方法是:将两个表中在共同数据项上相互匹配的那些行合并起来。
除――返回两个数据集之间的精确匹配。
此外,作为一种实现现代关系代数运算的方法,SQL还提供了:
子查询――类似于连接,但更灵活;在外部查询中,方式可以使用表达式、列表或者数据集合的地方都可以使用子查询的结果。
本章将主要讲述多种类型的连接、简单的和相关的子查询、几种类型的并、关系除以及其他的内容。
2 使用连接
2.1 连接类型
在关系代数中,连接运算是由一个笛卡尔积运算和一个选取运算构成的。首先用笛卡尔积完成对两个数据集合的乘运算,然后对生成的结果集合进行选取运算,确保只把分别来自两个数据集合并且具有重叠部分的行合并在一起。连接的全部意义在于在水平方向上合并两个数据集合(通常是表),并产生一个新的结果集合,其方法是将一个数据源中的行于另一个数据源中和它匹配的行组合成一个新元组。
SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。
连接类型 定义
内连接 只连接匹配的行
左外连接 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
右外连接 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
全外连接 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。
(H)(theta)连接 使用等值以外的条件来匹配左、右两个表中的行
交叉连接 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配
在INFORMIX中连接表的查询
如果FROM子句指定了多于一个表引用,则查询会连接来自多个表的行。连接条件指定各列之间(每个表至少一列)进行连接的关系。因为正在比较连接条件中的列,所以它们必须具有一致的数据类型。
SELECT语句的FROM子句可以指定以下几种类型的连接
FROM子句关键字 相应的结果集
CROSS JOIN 笛卡尔乘积(所有可能的行对)
INNER JOIN 仅对满足连接条件的CROSS中的列
LEFT OUTER JOIN 一个表满足条件的行,和另一个表的所有行
RIGHT OUTER JOIN 与LEFT相同,但两个表的角色互换
FULL OUTER JOIN LEFT OUTER 和 RIGHT OUTER中所有行的超集
2.2 内连接(Inner Join)
内连接是最常见的一种连接,它页被称为普通连接,而E.FCodd最早称之为自然连接。
下面是ANSI SQL-92标准
select *
from t_institution i
inner join t_teller t
on i.inst_no = t.inst_no
where i.inst_no = "5801"
其中inner可以省略。
等价于早期的连接语法
select *
from t_institution i, t_teller t
where i.inst_no = t.inst_no
and i.inst_no = "5801"
2.3 外连接
2.3.1 左外连接(Left Outer Jion)
select *
from t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
其中outer可以省略。
2.3.2 右外连接(Rigt Outer Jion)
select *
from t_institution i
right outer join t_teller t
on i.inst_no = t.inst_no
2.3.3 全外连接(Full Outer)
全外连接返回参与连接的两个数据集合中的全部数据,无论它们是否具有与之相匹配的行。在功能上,它等价于对这两个数据集合分别进行左外连接和右外连接,然后再使用消去重复行的并操作将上述两个结果集合并为一个结果集。
在现实生活中,参照完整性约束可以减少对于全外连接的使用,一般情况下左外连接就足够了。在数据库中没有利用清晰、规范的约束来防范错误数据情况下,全外连接就变得非常有用了,你可以使用它来清理数据库中的数据。
select *
from t_institution i
full outer join t_teller t
on i.inst_no = t.inst_no
2.3.4 外连接与条件配合使用
当在内连接查询中加入条件是,无论是将它加入到join子句,还是加入到where子句,其效果是完全一样的,但对于外连接情况就不同了。当把条件加入到join子句时,SQL Server、Informix会返回外连接表的全部行,然后使用指定的条件返回第二个表的行。如果将条件放到where子句中,SQL Server将会首先进行连接操作,然后使用where子句对连接后的行进行筛选。下面的两个查询展示了条件放置位子对执行结果的影响:
条件在join子句
select *
from t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
and i.inst_no = “5801”
结果是:
inst_no inst_name inst_no teller_no teller_name
5801 天河区 5801 0001 tom
5801 天河区 5801 0002 david
5802 越秀区
5803 白云区
条件在where子句
select *
from t_institution i
left outer join t_teller t
on i.inst_no = t.inst_no
where i.inst_no = “5801”
结果是:
inst_no inst_name inst_no teller_no teller_name
5801 天河区 5801 0001 tom
5801 天河区 5801 0002 david
2.4 自身连接
自身连接是指同一个表自己与自己进行连接。这种一元连接通常用于从自反关系(也称作递归关系)中抽取数据。例如人力资源数据库中雇员与老板的关系。
下面例子是在机构表中查找本机构和上级机构的信息。
select s.inst_no superior_inst, s.inst_name sup_inst_name, i.inst_no, i.inst_name
from t_institution i
join t_institution s
on i.superior_inst = s.inst_no
结果是:
superior_inst sup_inst_name inst_no inst_name
800 广州市 5801 天河区
800 广州市 5802 越秀区
800 广州市 5803 白云区
2.5 交叉(无) 连接
交叉连接用于对两个源表进行纯关系代数的乘运算。它不使用连接条件来结果集合,而是将分别来自两个数据源中的行以所有可能的方式进行组合。数据集合中一的每个行都要与数据集合二中的每一个行分别组成一个新的行。例如,如果第一个数据源中有5个行,而第二个数据源中有4个行,那么在它们之间进行交叉连接就会产生20个行。人们将这种类型的结果集称为笛卡尔乘积。
大多数交叉连接都是由于错误操作而造成的;但是它们却非常适合向数据库中填充例子数据,或者预先创建一些空行以便为程序执行期间所要填充的数据保留空间。
select *
from t_institution i
cross join t_teller t
在交叉连接中没有on条件子句
Inner Join
Inner Join 应该是最常用的 Join 方式, 它只会传回符合 Join 规则的纪录, 还是先来看看语法
Select <要选择的字段> From <主要资料表>
<Join 方式> <次要资料表> [On <Join 规则>]
Select ProctId, ProctName, Suppliers.SupplierId
From Procts
Inner Join Suppliers
Procts.Suppliers = Suppliers.SupplierId
Inner Join 的主要精神就是 exclusive , 叫它做排他性吧! 就是讲 Join 规则不相符的资料就会被排除掉,
譬如讲在 Proct 中有一项产品的供货商代码 (SupplierId), 没有出现在 Suppliers 资料表中, 那么这笔记录便会被排除掉
Outer Join
这款的 Join 方式是一般人比较少用到的, 甚至有些 SQL 的管理者也从未用过, 这真是一件悲哀的代志, 因为善用 Outer Join 是可以简化一些查询的工作的, 先来看看 Outer Join 的语法
Select <要查询的字段> From <Left 资料表>
<Left | Right> [Outer] Join <Right 资料表> On <Join 规则>
语法中的 Outer 是可以省略的, 例如你可以用 Left Join 或是 Right Join, 在本质上, Outer Join 是 inclusive, 叫它做包容性吧! 不同于 Inner Join 的排他性, 因此在 Left Outer Join 的查询结果会包含所有 Left 资料表的资料, 颠倒过来讲, Right Outer Join 的查询就会包含所有 Right 资料表的资料
总结:inner join是内部连接,outer join是外部接。inner求出的是交集,outer表示某个表的所有行,不管另一个表有没有这一行
INNER Join code as the following:
Select * from A a, B b where a.categoryID = b.categoryID;
equals:
Select * from A a inner join B b on a.categoryID = b.categoryID;
OUTER Join code as the following
select * from A a full(left/right) outer join B b on a on a.categoryID = b.categoryID;
left/right outer join claus specific for MSSQL:
Select * from A a, B b where a.categoryID *= bcategoryID;
elect * from A a, B b where a.categoryID =* b.categoryID;
left/right outer join claus specific for Oracle:
Select * from A a, B b where a.categoryID = b.categoryID(+);
Select * from A a, B b where a.categoryID (+) = b.categoryID;
参考资料:http://hi.baidu.com/279713119/blog/item/154503926e90f181a977a483.html
linq的 full join 怎么写
Linq to Sql:
var a=from g in Groups
join u in Users
on g.Id equals u.GroupId
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=g.GroupName, UserName=(grp==null)?"":grp.UserName};
var b=from u in Users
join g in Groups
on u.GroupId equals g.Id
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=(grp==null)?"":grp.GroupName, UserName=u.UserName};
var c=a.Concat(b).Distinct();
c.Dump();
Lambda:
Groups
.GroupJoin (
Users,
g => (Int32?)(g.Id),
u => u.GroupId,
(g, Grp) =>
new
{
g = g,
Grp = Grp
}
)
.SelectMany (
temp0 => temp0.Grp.DefaultIfEmpty (),
(temp0, grp) =>
new
{
GroupName = temp0.g.GroupName,
UserName = (grp == null) ? "" : grp.UserName
}
)
.Concat (
Users
.GroupJoin (
Groups,
u => u.GroupId,
g => (Int32?)(g.Id),
(u, Grp) =>
new
{
u = u,
Grp = Grp
}
)
.SelectMany (
temp2 => temp2.Grp.DefaultIfEmpty (),
(temp2, grp) =>
new
{
GroupName = (grp == null) ? "" : grp.GroupName,
UserName = temp2.u.UserName
}
)
)
.Distinct ()
linq的 full join 怎么写
Linq to Sql:
var a=from g in Groups
join u in Users
on g.Id equals u.GroupId
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=g.GroupName, UserName=(grp==null)?"":grp.UserName};
var b=from u in Users
join g in Groups
on u.GroupId equals g.Id
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=(grp==null)?"":grp.GroupName, UserName=u.UserName};
var c=a.Concat(b).Distinct();
c.Dump();
Lambda:
Groups
.GroupJoin (
Users,
g => (Int32?)(g.Id),
u => u.GroupId,
(g, Grp) =>
new
{
g = g,
Grp = Grp
}
)
.SelectMany (
temp0 => temp0.Grp.DefaultIfEmpty (),
(temp0, grp) =>
new
{
GroupName = temp0.g.GroupName,
UserName = (grp == null) ? "" : grp.UserName
}
)
.Concat (
Users
.GroupJoin (
Groups,
u => u.GroupId,
g => (Int32?)(g.Id),
(u, Grp) =>
new
{
u = u,
Grp = Grp
}
)
.SelectMany (
temp2 => temp2.Grp.DefaultIfEmpty (),
(temp2, grp) =>
new
{
GroupName = (grp == null) ? "" : grp.GroupName,
UserName = temp2.u.UserName
}
)
)
.Distinct ()
谁有关于linq的资料,急需
在达人博客上看到的:是个系列,一共三篇,你去百度搜搜“LINQ to SQL、NHibernate比较”就能找到了。我给你转第一篇。
LINQ to SQL、NHibernate比较(一)-- LINQ和NHibernate初体验
1 引言
研发与数据库打交道的系统的时候,最过于繁琐的莫过于没有编程快感的使用ADO.NET对后台数据库进行操作,因为所有的数据库连接、读取、操作千篇一律,编程成为了体力活。
虽然我们可以设计自己的类作为数据库访问的持久层,但是每一个类都必须有不相同的SQL语句,这样对于设计统一的数据库读写类造成了很大的困难。
开发人员在这种情况下必须包办窗体设计、方法设计、数据库读写设计的过程,这样加大了开发人员的负担也使得项目的维护和后期开发变得难以进行。
2 .NET下的ORM解决方案
2.1 LINQ
2.1.1 LINQ简介
作为微软开发的查询方案,LINQ 提供了一条更常规的途径即给 .Net Framework 添加一些可以应用于所有信息源( all sources of information )的具有多种用途( general-purpose )的语法查询特性( query facilities ),这是比向开发语言和运行时( runtime )添加一些关系数据( relational )特性或者类似 XML 特性( XML-specific )更好的方式。这些语法特性就叫做 .NET Language Integrated Query (LINQ) 。
如果觉得上面的解释有点抽象,那么可以这样理解,LINQ其实就是提供了一套查询功能,可以实现任何数据源的查询,此处数据源不单指数据库或者XML文件,而是任何集合或者实体,比如我们接触各种编程语言都需要用到的数组,现在不用遍历数组元素来寻找需要的项,LINQ可以实现这方面的查询。
LINQ查询数组:
图2.1 LINQ查询数组
上面是最简单的LINQ实现对数组的查询,泛型类型var在LINQ查询中提供了强大的委托类型支持,不管查询集合中项的类型(无论是int,char还是string或者类),我们只用一个var就可以保存LINQ查询到的结果。程序结果如下:
图2.2 LINQ查询数组程序结果
是不是很方便,LINQ的应用远远不这些,通过不同的映射方案,我们可以实现对数据库(LINQ To SQL),对XML文件(LINQ To XML)的访问。
2.1.2 LINQ简介
表2.1 LINQ的操作符
操作符
说明
聚合
Aggregate
对序列执行一个自定义方法
Average
计算数值序列的平均值
Count
返回序列中的项目数(整数)
LongCount
返回序列中的项目数(长型)
Min
查找数字序列中的最小数
Max
查找数字序列中的最大数
Sum
汇总序列中的数字
连接
Concat
将两个序列连成一个序列
转换
Cast
将序列中的元素转换成指定类型
OfType
筛选序列中指定类型的元素
ToArray
从序列返回一个数组
ToDictionary
从序列返回一个字典
ToList
从序列返回一个列表
ToLookup
从序列返回一个查询
ToSequence
返回一个 IEnumerable 序列
元素
DefaultIfEmpty
为空序列创建默认元素
ElementAt
返回序列中指定索引的元素
ElementAtOrDefault
返回序列中指定索引的元素,或者如果索引超出范围,则返回默认值
First
返回序列中的第一个元素
FirstOrDefault
返回序列中的第一个元素,或者如果未找到元素,则返回默认值
Last
返回序列中的最后一个元素
LastOrDefault
返回序列中的最后一个元素,或者如果未找到元素,则返回默认值
Single
返回序列中的单个元素
SingleOrDefault
返回序列中的单个元素,或者如果未找到元素,则返回默认值
相等
SequenceEqual
比较两个序列看其是否相等
生成
Empty
生成一个空序列
Range
生成一个指定范围的序列
Repeat
通过将某个项目重复指定次数来生成一个序列
分组
GroupBy
按指定分组方法对序列中的项目进行分组
联接
GroupJoin
通过归组将两个序列联接在一起
Join
将两个序列从内部联接起来
排序
OrderBy
以升序按值排列序列
OrderByDescending
以降序按值排列序列
ThenBy
升序排列已排序的序列
ThenByDescending
降序排列已排序的序列
Reverse
颠倒序列中项目的顺序
分区
Skip
返回跳过指定数目项目的序列
SkipWhile
返回跳过不满足表达式项目的序列
Take
返回具有指定数目项目的序列
TakeWhile
返回具有满足表达式项目的序列
投影
Select
创建部分序列的投影
SelectMany
创建部分序列的一对多投影
限定符
All
确定序列中的所有项目是否满足某个条件
Any
确定序列中是否有任何项目满足条件
Contains
确定序列是否包含指定项目
*
Where
筛选序列中的项目
设置
Distinct
返回无重复项目的序列
Except
返回代表两个序列差集的序列
Intersect
返回代表两个序列交集的序列
Union
返回代表两个序列交集的序列
Lambda 表达式
许多标准查询操作符在对序列执行运算时都使用 Func 委托来处理单个元素。Lambda 表达式可与标准查询操作符结合使用以代表委托。lambda 表达式是创建委托实现的简略表达形式,并可用于匿名委托适用的所有场合。C# 和 Visual Basic® .NET 均支持 Lambda 表达式。但是,必须注意:由于 Visual Basic .NET 尚不支持匿名方法,Lambda 表达式可能仅包含一个语句。
上例中的的程序等同于下面
图2.3 Lambda表达式的使用
2.2 NHibernate
说到NHibernate,就不得不提Hibernate,原因很简单,Hibernate顾名思义就是Hibernate的.NET版本。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具*意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
NHibernate作为Hibernate的.NET应用于Hibernate的实现完全相同,学习NHibernate完全可以直接学习Hibernate的资料。
事实上,虽然在Java数据库映射领域Hibernate是使用最为广泛的方案,但是在.NET中由于LINQ等映射方案(包括微软下一代重量级的Entity Framework)的使用,NHibernate冷了许多。
NHibernate需要配置数据库配置文件和类/表映射配置文件,所以使用NHibernate需要懂得XML文件的基础知识,并且需要掌握比较复杂的XML文件配置节和相应的配置命令。
2.2.1 数据库配置文件
NHibernate官方提供了配置文件的模板和实例可供我们参考。
图2.4 NHibernate官方数据库配置文件模板(对应了不同的数据库)
上图为数据库配置文件。通常以“cfg.xml”作为后缀,一个示例的文件内容如下
图2.5 数据库配置文件示例
下面是一些在运行时可以改变NHibernate行为的其他配置。所有这些都是可选的,也有合理的默认值。
表2.2 NHibernate 配置属性
属性名
用途
hibernate.dialect
NHibernate方言(Dialect)的类名 - 可以让NHibernate使用某些特定的数据库平台的特性
例如: full.classname.of.Dialect(如果方言创建在NHibernate中), 或者full.classname.of.Dialect, assembly (如果使用一个自定义的方言的实现,它不属于NHibernate)。
hibernate.default_schema
在生成的SQL中,scheml/tablespace的全限定名.
例如: SCHEMA_NAME
hibernate.prepare_sql
是否准备sql语句
例如: true | false
hibernate.session_factory_name
SessionFactory被创建后将自动绑定这个名称.
例如: some.name
hibernate.use_outer_join
允许使用外连接抓取。
例如:true | false
hibernate.cache.provider_class
指定一个自定义的CacheProvider缓存提供者的类名
例如: full.classname.of.CacheProvider(如果ICacheProvider创建在NHibernate中), 或full.classname.of.CacheProvider, assembly(如果使用一个自定义的ICacheProvider,它不属于NHibernate)。
hibernate.query.substitutions
把NHibernate查询中的一些短语替换为SQL短语(比如说短语可能是函数或者字符)。
例如: hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
2.2.2 实体映射配置文件
NHibernate官方开源包中提供了实体映射配置文件的实例可供我们参考。
图2.6 NHibernate开源包中提供的实体映射配置文件
与数据库配置文件一样实体映射配置文件也是XML文件(XML果然是很强大啊,微软下一代应用程序开发技术WPF就是使用XML文件将C/S和B/S长期分居的二人统一到一个屋檐下),所不同的是实体映射配置文件后缀是“hbm.xml”。
图2.7 实体映射配置文件
实体映射配置文件所要配置的信息一般为
Ø Schema
所有的XML映射都需要使用nhibernate-mapping-2.0 schema。目前的schema可以在NHibernate的资源路径或者是NHibernate.dll的嵌入资源(Embedded Resource)中找到。NHibernate总是会优先使用嵌入在资源中的schema文件。
Ø hibernate-mapping
(1)
schema (可选): 数据库schema名称.
(2)
default-cascade (可选 - 默认为 none): 默认的级联风格.
(3)
auto-import (可选 - 默认为 true): 指定是否我们可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。
(4)
default-access (可选 - 默认为 property): NHibernate访问属性值时的策略。
(5)
assembly (可选): 指定一个程序集,如果在映射文档中没有指定程序集,就使用这个程序集。
(6)
namespace (可选): 指定一个命名空间前缀,如果在映射文档中没有指定全限定名,就使用这个命名空间名。
Ø class (1)
name: 持久化类(或者接口)的全限定名。
(2)
table: 对应的数据库表名。
(3)
discriminator-value (可选 - 默认和类名一样): 一个用于区分不同的子类的值,在多态行为时使用。
(4)
mutable (可选, 默认为 true): 表明该类的实例可变(不可变)。
(5)
schema (可选): 覆盖在根<hibernate-mapping> 元素中指定的schema名字。
(6)
proxy (可选): 指定一个接口,在延迟装载时作为代理使用。你可以在这里使用该类自己的名字。
(7)
dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。
(8)
dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。
(9)
polymorphism (可选, 默认为 implicit(隐式)): 界定是隐式还是显式的使用查询多态。
(10)
where (可选) 指定一个附加的SQL WHERE 条件,在抓取这个类的对象时会一直增加这个条件。
(11)
persister (可选): 指定一个定制的 IClassPersister.
(12)
lazy(可选):假若设置 lazy="true",就是设置这个类自己的名字作为proxy接口的一种等价快捷形式。
Ø id (1)
name (可选): 标识属性的名字。
(2)
type (可选): 标识NHibernate类型的名字。
(3)
column (可选 - 默认为属性名): 主键字段的名字。
(4)
unsaved-value (可选 - 默认为 null): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注)但未再次持久化的实例区分开来。
(5)
access (可选 - 默认为 property): NHibernate用来访问属性值的策略。
除此之外我们可以通过其他途径深入了解配置方面的知识,一个NHibernate项目,配置文件的错误往往导致错误的结果甚至使得程序无法运行。
3 小结
本文初步介绍了LINQ to SQL和NHibernate,其中介绍NHibernate使用了较多的篇幅,因为相对LINQ to SQL而言NHibernate的使用入门门槛较高,配置较为复杂。关于LINQ to SQL、NHibernate优缺点将在后面文章中讨论,不过从此处其实已经得出一点,那就是LINQ to SQL比NHibernate更加容易上手,节省了人员培训的开销。
谁有关于linq的资料,急需
在达人博客上看到的:是个系列,一共三篇,你去百度搜搜“LINQ to SQL、NHibernate比较”就能找到了。我给你转第一篇。
LINQ to SQL、NHibernate比较(一)-- LINQ和NHibernate初体验
1 引言
研发与数据库打交道的系统的时候,最过于繁琐的莫过于没有编程快感的使用ADO.NET对后台数据库进行操作,因为所有的数据库连接、读取、操作千篇一律,编程成为了体力活。
虽然我们可以设计自己的类作为数据库访问的持久层,但是每一个类都必须有不相同的SQL语句,这样对于设计统一的数据库读写类造成了很大的困难。
开发人员在这种情况下必须包办窗体设计、方法设计、数据库读写设计的过程,这样加大了开发人员的负担也使得项目的维护和后期开发变得难以进行。
2 .NET下的ORM解决方案
2.1 LINQ
2.1.1 LINQ简介
作为微软开发的查询方案,LINQ 提供了一条更常规的途径即给 .Net Framework 添加一些可以应用于所有信息源( all sources of information )的具有多种用途( general-purpose )的语法查询特性( query facilities ),这是比向开发语言和运行时( runtime )添加一些关系数据( relational )特性或者类似 XML 特性( XML-specific )更好的方式。这些语法特性就叫做 .NET Language Integrated Query (LINQ) 。
如果觉得上面的解释有点抽象,那么可以这样理解,LINQ其实就是提供了一套查询功能,可以实现任何数据源的查询,此处数据源不单指数据库或者XML文件,而是任何集合或者实体,比如我们接触各种编程语言都需要用到的数组,现在不用遍历数组元素来寻找需要的项,LINQ可以实现这方面的查询。
LINQ查询数组:
图2.1 LINQ查询数组
上面是最简单的LINQ实现对数组的查询,泛型类型var在LINQ查询中提供了强大的委托类型支持,不管查询集合中项的类型(无论是int,char还是string或者类),我们只用一个var就可以保存LINQ查询到的结果。程序结果如下:
图2.2 LINQ查询数组程序结果
是不是很方便,LINQ的应用远远不这些,通过不同的映射方案,我们可以实现对数据库(LINQ To SQL),对XML文件(LINQ To XML)的访问。
2.1.2 LINQ简介
表2.1 LINQ的操作符
操作符
说明
聚合
Aggregate
对序列执行一个自定义方法
Average
计算数值序列的平均值
Count
返回序列中的项目数(整数)
LongCount
返回序列中的项目数(长型)
Min
查找数字序列中的最小数
Max
查找数字序列中的最大数
Sum
汇总序列中的数字
连接
Concat
将两个序列连成一个序列
转换
Cast
将序列中的元素转换成指定类型
OfType
筛选序列中指定类型的元素
ToArray
从序列返回一个数组
ToDictionary
从序列返回一个字典
ToList
从序列返回一个列表
ToLookup
从序列返回一个查询
ToSequence
返回一个 IEnumerable 序列
元素
DefaultIfEmpty
为空序列创建默认元素
ElementAt
返回序列中指定索引的元素
ElementAtOrDefault
返回序列中指定索引的元素,或者如果索引超出范围,则返回默认值
First
返回序列中的第一个元素
FirstOrDefault
返回序列中的第一个元素,或者如果未找到元素,则返回默认值
Last
返回序列中的最后一个元素
LastOrDefault
返回序列中的最后一个元素,或者如果未找到元素,则返回默认值
Single
返回序列中的单个元素
SingleOrDefault
返回序列中的单个元素,或者如果未找到元素,则返回默认值
相等
SequenceEqual
比较两个序列看其是否相等
生成
Empty
生成一个空序列
Range
生成一个指定范围的序列
Repeat
通过将某个项目重复指定次数来生成一个序列
分组
GroupBy
按指定分组方法对序列中的项目进行分组
联接
GroupJoin
通过归组将两个序列联接在一起
Join
将两个序列从内部联接起来
排序
OrderBy
以升序按值排列序列
OrderByDescending
以降序按值排列序列
ThenBy
升序排列已排序的序列
ThenByDescending
降序排列已排序的序列
Reverse
颠倒序列中项目的顺序
分区
Skip
返回跳过指定数目项目的序列
SkipWhile
返回跳过不满足表达式项目的序列
Take
返回具有指定数目项目的序列
TakeWhile
返回具有满足表达式项目的序列
投影
Select
创建部分序列的投影
SelectMany
创建部分序列的一对多投影
限定符
All
确定序列中的所有项目是否满足某个条件
Any
确定序列中是否有任何项目满足条件
Contains
确定序列是否包含指定项目
*
Where
筛选序列中的项目
设置
Distinct
返回无重复项目的序列
Except
返回代表两个序列差集的序列
Intersect
返回代表两个序列交集的序列
Union
返回代表两个序列交集的序列
Lambda 表达式
许多标准查询操作符在对序列执行运算时都使用 Func 委托来处理单个元素。Lambda 表达式可与标准查询操作符结合使用以代表委托。lambda 表达式是创建委托实现的简略表达形式,并可用于匿名委托适用的所有场合。C# 和 Visual Basic® .NET 均支持 Lambda 表达式。但是,必须注意:由于 Visual Basic .NET 尚不支持匿名方法,Lambda 表达式可能仅包含一个语句。
上例中的的程序等同于下面
图2.3 Lambda表达式的使用
2.2 NHibernate
说到NHibernate,就不得不提Hibernate,原因很简单,Hibernate顾名思义就是Hibernate的.NET版本。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具*意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
NHibernate作为Hibernate的.NET应用于Hibernate的实现完全相同,学习NHibernate完全可以直接学习Hibernate的资料。
事实上,虽然在Java数据库映射领域Hibernate是使用最为广泛的方案,但是在.NET中由于LINQ等映射方案(包括微软下一代重量级的Entity Framework)的使用,NHibernate冷了许多。
NHibernate需要配置数据库配置文件和类/表映射配置文件,所以使用NHibernate需要懂得XML文件的基础知识,并且需要掌握比较复杂的XML文件配置节和相应的配置命令。
2.2.1 数据库配置文件
NHibernate官方提供了配置文件的模板和实例可供我们参考。
图2.4 NHibernate官方数据库配置文件模板(对应了不同的数据库)
上图为数据库配置文件。通常以“cfg.xml”作为后缀,一个示例的文件内容如下
图2.5 数据库配置文件示例
下面是一些在运行时可以改变NHibernate行为的其他配置。所有这些都是可选的,也有合理的默认值。
表2.2 NHibernate 配置属性
属性名
用途
hibernate.dialect
NHibernate方言(Dialect)的类名 - 可以让NHibernate使用某些特定的数据库平台的特性
例如: full.classname.of.Dialect(如果方言创建在NHibernate中), 或者full.classname.of.Dialect, assembly (如果使用一个自定义的方言的实现,它不属于NHibernate)。
hibernate.default_schema
在生成的SQL中,scheml/tablespace的全限定名.
例如: SCHEMA_NAME
hibernate.prepare_sql
是否准备sql语句
例如: true | false
hibernate.session_factory_name
SessionFactory被创建后将自动绑定这个名称.
例如: some.name
hibernate.use_outer_join
允许使用外连接抓取。
例如:true | false
hibernate.cache.provider_class
指定一个自定义的CacheProvider缓存提供者的类名
例如: full.classname.of.CacheProvider(如果ICacheProvider创建在NHibernate中), 或full.classname.of.CacheProvider, assembly(如果使用一个自定义的ICacheProvider,它不属于NHibernate)。
hibernate.query.substitutions
把NHibernate查询中的一些短语替换为SQL短语(比如说短语可能是函数或者字符)。
例如: hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
2.2.2 实体映射配置文件
NHibernate官方开源包中提供了实体映射配置文件的实例可供我们参考。
图2.6 NHibernate开源包中提供的实体映射配置文件
与数据库配置文件一样实体映射配置文件也是XML文件(XML果然是很强大啊,微软下一代应用程序开发技术WPF就是使用XML文件将C/S和B/S长期分居的二人统一到一个屋檐下),所不同的是实体映射配置文件后缀是“hbm.xml”。
图2.7 实体映射配置文件
实体映射配置文件所要配置的信息一般为
Ø Schema
所有的XML映射都需要使用nhibernate-mapping-2.0 schema。目前的schema可以在NHibernate的资源路径或者是NHibernate.dll的嵌入资源(Embedded Resource)中找到。NHibernate总是会优先使用嵌入在资源中的schema文件。
Ø hibernate-mapping
(1)
schema (可选): 数据库schema名称.
(2)
default-cascade (可选 - 默认为 none): 默认的级联风格.
(3)
auto-import (可选 - 默认为 true): 指定是否我们可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。
(4)
default-access (可选 - 默认为 property): NHibernate访问属性值时的策略。
(5)
assembly (可选): 指定一个程序集,如果在映射文档中没有指定程序集,就使用这个程序集。
(6)
namespace (可选): 指定一个命名空间前缀,如果在映射文档中没有指定全限定名,就使用这个命名空间名。
Ø class (1)
name: 持久化类(或者接口)的全限定名。
(2)
table: 对应的数据库表名。
(3)
discriminator-value (可选 - 默认和类名一样): 一个用于区分不同的子类的值,在多态行为时使用。
(4)
mutable (可选, 默认为 true): 表明该类的实例可变(不可变)。
(5)
schema (可选): 覆盖在根<hibernate-mapping> 元素中指定的schema名字。
(6)
proxy (可选): 指定一个接口,在延迟装载时作为代理使用。你可以在这里使用该类自己的名字。
(7)
dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。
(8)
dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。
(9)
polymorphism (可选, 默认为 implicit(隐式)): 界定是隐式还是显式的使用查询多态。
(10)
where (可选) 指定一个附加的SQL WHERE 条件,在抓取这个类的对象时会一直增加这个条件。
(11)
persister (可选): 指定一个定制的 IClassPersister.
(12)
lazy(可选):假若设置 lazy="true",就是设置这个类自己的名字作为proxy接口的一种等价快捷形式。
Ø id (1)
name (可选): 标识属性的名字。
(2)
type (可选): 标识NHibernate类型的名字。
(3)
column (可选 - 默认为属性名): 主键字段的名字。
(4)
unsaved-value (可选 - 默认为 null): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注)但未再次持久化的实例区分开来。
(5)
access (可选 - 默认为 property): NHibernate用来访问属性值的策略。
除此之外我们可以通过其他途径深入了解配置方面的知识,一个NHibernate项目,配置文件的错误往往导致错误的结果甚至使得程序无法运行。
3 小结
本文初步介绍了LINQ to SQL和NHibernate,其中介绍NHibernate使用了较多的篇幅,因为相对LINQ to SQL而言NHibernate的使用入门门槛较高,配置较为复杂。关于LINQ to SQL、NHibernate优缺点将在后面文章中讨论,不过从此处其实已经得出一点,那就是LINQ to SQL比NHibernate更加容易上手,节省了人员培训的开销。
linq to sql 使用 => 表达式,怎么设置where A表某字段==B表某字段?
var result = from a in A表
join b in B表
on a.某字段 equals b.某字段
select new
{
a.XXX,
b.XXX
};
或者
var result = from a in A表
from b in B表
where a.某字段 == b.某字段
select new
{
a.XXX,
b.XXX
};追问谢谢,不过像zhouji432600 说的,=> 无法实现么?
追答呃,为啥非要写Lamda表达式呢?可以写,但是有点麻烦。
var A = from p in A表
select p;
var B = from p in B表
select p;
var result = A.Join(B,
a => a.某字段,
b => b.某字段,
(a, b) => new {
a.XXX,
b.XXX
}
);
result就是结果了,遍历一下获取你的数据。
怎么用Linq链接两张数据表再查询出数据
使用join来连接
Enumerable.Join<TOuter, TInner, TKey, TResult> 方法 (IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>)
发送反馈
基于匹配键对两个序列的元素进行关联。
使用默认的相等比较器对键进行比较。
命名空间: System.Linq
程序集: System.Core(在 System.Core.dll 中)
语法
--------------------------------------------------------------------------------
VBC#C++F#JScript以带有颜色区分的格式查看复制到剪贴板打印<ExtensionAttribute> _
Public Shared Function Join(Of TOuter, TInner, TKey, TResult) ( _
outer As IEnumerable(Of TOuter), _
inner As IEnumerable(Of TInner), _
outerKeySelector As Func(Of TOuter, TKey), _
innerKeySelector As Func(Of TInner, TKey), _
resultSelector As Func(Of TOuter, TInner, TResult) _
) As IEnumerable(Of TResult)
<ExtensionAttribute> _
Public Shared Function Join(Of TOuter, TInner, TKey, TResult) ( _
outer As IEnumerable(Of TOuter), _
inner As IEnumerable(Of TInner), _
outerKeySelector As Func(Of TOuter, TKey), _
innerKeySelector As Func(Of TInner, TKey), _
resultSelector As Func(Of TOuter, TInner, TResult) _
) As IEnumerable(Of TResult)
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
[ExtensionAttribute]
public:
generic<typename TOuter, typename TInner, typename TKey, typename TResult>
static IEnumerable<TResult>^ Join(
IEnumerable<TOuter>^ outer,
IEnumerable<TInner>^ inner,
Func<TOuter, TKey>^ outerKeySelector,
Func<TInner, TKey>^ innerKeySelector,
Func<TOuter, TInner, TResult>^ resultSelector
)
[ExtensionAttribute]
public:
generic<typename TOuter, typename TInner, typename TKey, typename TResult>
static IEnumerable<TResult>^ Join(
IEnumerable<TOuter>^ outer,
IEnumerable<TInner>^ inner,
Func<TOuter, TKey>^ outerKeySelector,
Func<TInner, TKey>^ innerKeySelector,
Func<TOuter, TInner, TResult>^ resultSelector
)
static member Join :
outer:IEnumerable<'TOuter> *
inner:IEnumerable<'TInner> *
outerKeySelector:Func<'TOuter, 'TKey> *
innerKeySelector:Func<'TInner, 'TKey> *
resultSelector:Func<'TOuter, 'TInner, 'TResult> -> IEnumerable<'TResult>
static member Join :
outer:IEnumerable<'TOuter> *
inner:IEnumerable<'TInner> *
outerKeySelector:Func<'TOuter, 'TKey> *
innerKeySelector:Func<'TInner, 'TKey> *
resultSelector:Func<'TOuter, 'TInner, 'TResult> -> IEnumerable<'TResult>
类型参数
TOuter
第一个序列中的元素的类型。
TInner
第二个序列中的元素的类型。
TKey
键选择器函数返回的键的类型。
TResult
结果元素的类型。
参数
outer
类型: System.Collections.Generic.IEnumerable <TOuter>
要联接的第一个序列。
inner
类型: System.Collections.Generic.IEnumerable <TInner>
要与第一个序列联接的序列。
outerKeySelector
类型: System.Func <TOuter, TKey>
用于从第一个序列的每个元素提取联接键的函数。
innerKeySelector
类型: System.Func <TInner, TKey>
用于从第二个序列的每个元素提取联接键的函数。
resultSelector
类型: System.Func <TOuter, TInner, TResult>
用于从两个匹配元素创建结果元素的函数。
返回值
类型: System.Collections.Generic.IEnumerable <TResult>
一个具有 TResult 类型元素的 IEnumerable<T>,这些元素是通过对两个序列执行内部联接得来的。
使用说明
在 Visual Basic 和 C# 中,可以在 IEnumerable<TOuter> 类型的任何对象上将此方法作为实例方法来调用。当使用实例方法语法调用此方法时,请省略第一个参数。有关更多信息,请参见 扩展方法 (Visual Basic)或 扩展方法(C# 编程指南)。
异常
--------------------------------------------------------------------------------
异常 条件
ArgumentNullException
outer 或 inner 或 outerKeySelector 或 innerKeySelector 或 resultSelector 为 null。
备注
--------------------------------------------------------------------------------
此方法通过使用延迟执行实现。
即时返回值为一个对象,该对象存储执行操作所需的所有信息。
只有通过直接调用对象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)来枚举该对象时,才执行此方法表示的查询。
使用默认的相等比较器 Default 对键进行哈希处理和比较。
联接是指基于某个公共键使两个信息源的元素相关联的操作。
Join 在一个方法调用中产生两个信息源和使它们相匹配的密钥。
这与 SelectMany 的用法不同,后者需要一个以上的方法调用才可以执行相同的操作。
Join 保留 outer 中的元素的顺序,并且对于这些元素中的每一个元素,保留 inner 中的匹配元素的顺序。
在查询表达式语法中, join (Visual C#) 或 Join (Visual Basic) 子句转换为 Join 的一个调用。
在关系数据库术语中, Join 方法实现内部同等联接。'
“内部”表示结果中仅包含在另一序列中具有匹配项的元素。
“同等联接”是在其中比较键是否相等的联接。
左外部联接操作没有专用的标准查询运算符,但可以使用 GroupJoin 方法执行此操作。
请参见 联接运算。
示例
--------------------------------------------------------------------------------
下面的代码示例演示如何使用 Join<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>) 基于公共键对两个序列执行内部联接。
VBC#C++F#JScript以带有颜色区分的格式查看复制到剪贴板打印Structure Person
Public Name As String
End Structure
Structure Pet
Public Name As String
Public Owner As Person
End Structure
Sub JoinEx1()
Dim magnus As New Person With {.Name = "Hedlund, Magnus"}
Dim terry As New Person With {.Name = "Adams, Terry"}
Dim charlotte As New Person With {.Name = "Weiss, Charlotte"}
Dim barley As New Pet With {.Name = "Barley", .Owner = terry}
Dim boots As New Pet With {.Name = "Boots", .Owner = terry}
Dim whiskers As New Pet With {.Name = "Whiskers", .Owner = charlotte}
Dim daisy As New Pet With {.Name = "Daisy", .Owner = magnus}
Dim people As New List(Of Person)(New Person() {magnus, terry, charlotte})
Dim pets As New List(Of Pet)(New Pet() {barley, boots, whiskers, daisy})
' Create a list of Person-Pet pairs, where each element is an
' anonymous type that contains a Pet's name and the name of the
' Person that owns the Pet.
Dim query = _
people.Join(pets, _
Function(person) person, _
Function(pet) pet.Owner, _
Function(person, pet) _
New With {.OwnerName = person.Name, .Pet = pet.Name})
Dim output As New System.Text.StringBuilder
For Each obj In query
output.AppendLine(obj.OwnerName & " - " & obj.Pet)
Next
' Display the output.
MsgBox(output.ToString)
End Sub
' This code proces the following output:
'
' Hedlund, Magnus - Daisy
' Adams, Terry - Barley
' Adams, Terry - Boots
' Weiss, Charlotte - Whiskers
Structure Person
Public Name As String
End Structure
Structure Pet
Public Name As String
Public Owner As Person
End Structure
Sub JoinEx1()
Dim magnus As New Person With {.Name = "Hedlund, Magnus"}
Dim terry As New Person With {.Name = "Adams, Terry"}
Dim charlotte As New Person With {.Name = "Weiss, Charlotte"}
Dim barley As New Pet With {.Name = "Barley", .Owner = terry}
Dim boots As New Pet With {.Name = "Boots", .Owner = terry}
Dim whiskers As New Pet With {.Name = "Whiskers", .Owner = charlotte}
Dim daisy As New Pet With {.Name = "Daisy", .Owner = magnus}
Dim people As New List(Of Person)(New Person() {magnus, terry, charlotte})
Dim pets As New List(Of Pet)(New Pet() {barley, boots, whiskers, daisy})
' Create a list of Person-Pet pairs, where each element is an
' anonymous type that contains a Pet's name and the name of the
' Person that owns the Pet.
Dim query = _
people.Join(pets, _
Function(person) person, _
Function(pet) pet.Owner, _
Function(person, pet) _
New With {.OwnerName = person.Name, .Pet = pet.Name})
Dim output As New System.Text.StringBuilder
For Each obj In query
output.AppendLine(obj.OwnerName & " - " & obj.Pet)
Next
' Display the output.
MsgBox(output.ToString)
End Sub
' This code proces the following output:
'
' Hedlund, Magnus - Daisy
' Adams, Terry - Barley
' Adams, Terry - Boots
' Weiss, Charlotte - Whiskers
怎么用Linq链接两张数据表再查询出数据
使用join来连接
Enumerable.Join<TOuter, TInner, TKey, TResult> 方法 (IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>)
发送反馈
基于匹配键对两个序列的元素进行关联。
使用默认的相等比较器对键进行比较。
命名空间: System.Linq
程序集: System.Core(在 System.Core.dll 中)
语法
--------------------------------------------------------------------------------
VBC#C++F#JScript以带有颜色区分的格式查看复制到剪贴板打印<ExtensionAttribute> _
Public Shared Function Join(Of TOuter, TInner, TKey, TResult) ( _
outer As IEnumerable(Of TOuter), _
inner As IEnumerable(Of TInner), _
outerKeySelector As Func(Of TOuter, TKey), _
innerKeySelector As Func(Of TInner, TKey), _
resultSelector As Func(Of TOuter, TInner, TResult) _
) As IEnumerable(Of TResult)
<ExtensionAttribute> _
Public Shared Function Join(Of TOuter, TInner, TKey, TResult) ( _
outer As IEnumerable(Of TOuter), _
inner As IEnumerable(Of TInner), _
outerKeySelector As Func(Of TOuter, TKey), _
innerKeySelector As Func(Of TInner, TKey), _
resultSelector As Func(Of TOuter, TInner, TResult) _
) As IEnumerable(Of TResult)
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
[ExtensionAttribute]
public:
generic<typename TOuter, typename TInner, typename TKey, typename TResult>
static IEnumerable<TResult>^ Join(
IEnumerable<TOuter>^ outer,
IEnumerable<TInner>^ inner,
Func<TOuter, TKey>^ outerKeySelector,
Func<TInner, TKey>^ innerKeySelector,
Func<TOuter, TInner, TResult>^ resultSelector
)
[ExtensionAttribute]
public:
generic<typename TOuter, typename TInner, typename TKey, typename TResult>
static IEnumerable<TResult>^ Join(
IEnumerable<TOuter>^ outer,
IEnumerable<TInner>^ inner,
Func<TOuter, TKey>^ outerKeySelector,
Func<TInner, TKey>^ innerKeySelector,
Func<TOuter, TInner, TResult>^ resultSelector
)
static member Join :
outer:IEnumerable<'TOuter> *
inner:IEnumerable<'TInner> *
outerKeySelector:Func<'TOuter, 'TKey> *
innerKeySelector:Func<'TInner, 'TKey> *
resultSelector:Func<'TOuter, 'TInner, 'TResult> -> IEnumerable<'TResult>
static member Join :
outer:IEnumerable<'TOuter> *
inner:IEnumerable<'TInner> *
outerKeySelector:Func<'TOuter, 'TKey> *
innerKeySelector:Func<'TInner, 'TKey> *
resultSelector:Func<'TOuter, 'TInner, 'TResult> -> IEnumerable<'TResult>
类型参数
TOuter
第一个序列中的元素的类型。
TInner
第二个序列中的元素的类型。
TKey
键选择器函数返回的键的类型。
TResult
结果元素的类型。
参数
outer
类型: System.Collections.Generic.IEnumerable <TOuter>
要联接的第一个序列。
inner
类型: System.Collections.Generic.IEnumerable <TInner>
要与第一个序列联接的序列。
outerKeySelector
类型: System.Func <TOuter, TKey>
用于从第一个序列的每个元素提取联接键的函数。
innerKeySelector
类型: System.Func <TInner, TKey>
用于从第二个序列的每个元素提取联接键的函数。
resultSelector
类型: System.Func <TOuter, TInner, TResult>
用于从两个匹配元素创建结果元素的函数。
返回值
类型: System.Collections.Generic.IEnumerable <TResult>
一个具有 TResult 类型元素的 IEnumerable<T>,这些元素是通过对两个序列执行内部联接得来的。
使用说明
在 Visual Basic 和 C# 中,可以在 IEnumerable<TOuter> 类型的任何对象上将此方法作为实例方法来调用。当使用实例方法语法调用此方法时,请省略第一个参数。有关更多信息,请参见 扩展方法 (Visual Basic)或 扩展方法(C# 编程指南)。
异常
--------------------------------------------------------------------------------
异常 条件
ArgumentNullException
outer 或 inner 或 outerKeySelector 或 innerKeySelector 或 resultSelector 为 null。
备注
--------------------------------------------------------------------------------
此方法通过使用延迟执行实现。
即时返回值为一个对象,该对象存储执行操作所需的所有信息。
只有通过直接调用对象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)来枚举该对象时,才执行此方法表示的查询。
使用默认的相等比较器 Default 对键进行哈希处理和比较。
联接是指基于某个公共键使两个信息源的元素相关联的操作。
Join 在一个方法调用中产生两个信息源和使它们相匹配的密钥。
这与 SelectMany 的用法不同,后者需要一个以上的方法调用才可以执行相同的操作。
Join 保留 outer 中的元素的顺序,并且对于这些元素中的每一个元素,保留 inner 中的匹配元素的顺序。
在查询表达式语法中, join (Visual C#) 或 Join (Visual Basic) 子句转换为 Join 的一个调用。
在关系数据库术语中, Join 方法实现内部同等联接。'
“内部”表示结果中仅包含在另一序列中具有匹配项的元素。
“同等联接”是在其中比较键是否相等的联接。
左外部联接操作没有专用的标准查询运算符,但可以使用 GroupJoin 方法执行此操作。
请参见 联接运算。
示例
--------------------------------------------------------------------------------
下面的代码示例演示如何使用 Join<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter, TKey>, Func<TInner, TKey>, Func<TOuter, TInner, TResult>) 基于公共键对两个序列执行内部联接。
VBC#C++F#JScript以带有颜色区分的格式查看复制到剪贴板打印Structure Person
Public Name As String
End Structure
Structure Pet
Public Name As String
Public Owner As Person
End Structure
Sub JoinEx1()
Dim magnus As New Person With {.Name = "Hedlund, Magnus"}
Dim terry As New Person With {.Name = "Adams, Terry"}
Dim charlotte As New Person With {.Name = "Weiss, Charlotte"}
Dim barley As New Pet With {.Name = "Barley", .Owner = terry}
Dim boots As New Pet With {.Name = "Boots", .Owner = terry}
Dim whiskers As New Pet With {.Name = "Whiskers", .Owner = charlotte}
Dim daisy As New Pet With {.Name = "Daisy", .Owner = magnus}
Dim people As New List(Of Person)(New Person() {magnus, terry, charlotte})
Dim pets As New List(Of Pet)(New Pet() {barley, boots, whiskers, daisy})
' Create a list of Person-Pet pairs, where each element is an
' anonymous type that contains a Pet's name and the name of the
' Person that owns the Pet.
Dim query = _
people.Join(pets, _
Function(person) person, _
Function(pet) pet.Owner, _
Function(person, pet) _
New With {.OwnerName = person.Name, .Pet = pet.Name})
Dim output As New System.Text.StringBuilder
For Each obj In query
output.AppendLine(obj.OwnerName & " - " & obj.Pet)
Next
' Display the output.
MsgBox(output.ToString)
End Sub
' This code proces the following output:
'
' Hedlund, Magnus - Daisy
' Adams, Terry - Barley
' Adams, Terry - Boots
' Weiss, Charlotte - Whiskers
Structure Person
Public Name As String
End Structure
Structure Pet
Public Name As String
Public Owner As Person
End Structure
Sub JoinEx1()
Dim magnus As New Person With {.Name = "Hedlund, Magnus"}
Dim terry As New Person With {.Name = "Adams, Terry"}
Dim charlotte As New Person With {.Name = "Weiss, Charlotte"}
Dim barley As New Pet With {.Name = "Barley", .Owner = terry}
Dim boots As New Pet With {.Name = "Boots", .Owner = terry}
Dim whiskers As New Pet With {.Name = "Whiskers", .Owner = charlotte}
Dim daisy As New Pet With {.Name = "Daisy", .Owner = magnus}
Dim people As New List(Of Person)(New Person() {magnus, terry, charlotte})
Dim pets As New List(Of Pet)(New Pet() {barley, boots, whiskers, daisy})
' Create a list of Person-Pet pairs, where each element is an
' anonymous type that contains a Pet's name and the name of the
' Person that owns the Pet.
Dim query = _
people.Join(pets, _
Function(person) person, _
Function(pet) pet.Owner, _
Function(person, pet) _
New With {.OwnerName = person.Name, .Pet = pet.Name})
Dim output As New System.Text.StringBuilder
For Each obj In query
output.AppendLine(obj.OwnerName & " - " & obj.Pet)
Next
' Display the output.
MsgBox(output.ToString)
End Sub
' This code proces the following output:
'
' Hedlund, Magnus - Daisy
' Adams, Terry - Barley
' Adams, Terry - Boots
' Weiss, Charlotte - Whiskers