C#中Linq常用用法
LINQ查询语法
有两种基本的方法来编写一个LINQ查询IEnumerable集合或IQueryable数据源。
1、查询语法或查询表达式语法
2、方法语法或方法扩展语法或Fluent
LINQ查询语法
查询语法与数据库的SQL(结构化查询语言)类似。它是在C#或VB代码中定义的。
具体的语法:
(1)从<范围变量>在<IEnumerable 或IQueryable 集合>
(2)<标准查询运算符> <lambda表达式>
(3)<select或groupBy运算符> <结果形成>
LINQ查询语法从关键字开始,以select关键字结束。以下是LINQ查询示例,它返回包含单词“Tutorials”的字符串集合。
查询语法从一个From子句开始,然后是一个Range变量。在从子句结构类似,意味着从集合中的每个对象。
它类似于一个foreach循环:"From> rangeVariableName in IEnumerablecollection"foreach(Student s in studentList)
在From子句之后,可以使用不同的标准查询运算符来过滤,分组和集合的元素。在LINQ中有大约50个标准查询操作符可用。在上图中,我们使用了“where”运算符(aka子句)后跟一个条件。这个条件通常用lambda表达式表示。
LINQ查询语法总是以Select或Group子句结束。Select子句用于形成数据。您可以按原样选择整个对象,也可以仅选择其中的一些属性。在上面的例子中,我们选择了每个结果字符串元素。
LINQ方法语法
方法语法(也称为流利语法)使用Enumerable或Queryable静态类中包含的扩展方法,类似于您将如何调用任何类的扩展方法。
————————————————
版权声明:本文为CSDN博主「Hi-Sunshine」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zmh458/article/details/78935181
1、linq中交集、并集、差集的用法
简单的交集、并集、差集用法如下:
List<string> ListA = new List<string>();
List<string> ListB = new List<string>();
List<string> ListResult = new List<string>();
ListResult = ListA.Distinct().ToList();//去重
ListResult = ListA.Except(ListB).ToList();//差集
ListResult = ListA.Union(ListB).ToList(); //并集
ListResult = ListA.Intersect(ListB).ToList();//交集
若上面的例子不是List类型,而是List,则需要对XXXModel进行处理。
步骤如下:
(1)先定义Model。
public class ItemModel
{
public string ItemCode { get; set; }
public string ItemName { get; set; }
}
(2)定义如何Model间如何比较。若不定义,比较的是两个引用。
public class ItemModelComparer : IEqualityComparer<ItemModel>
{
//比较
public bool Equals(ItemModel x, ItemModel y)
{
bool checkFlag = true;
if (Object.ReferenceEquals(x, y))
{
checkFlag = true;
}
else if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
{
checkFlag = false;
}
else
{
if (x.ItemCode == y.ItemCode)
{
checkFlag = true;
}
else
{
checkFlag = false;
}
}
return checkFlag;
}
//实现获取哈希值
public int GetHashCode(ItemModel model)
{
if (Object.ReferenceEquals(model, null)) return 0;
int hashNurse = model.ItemCode.GetHashCode();
return hashNurse;
}
}
(3)具体使用如下
List<ItemModel> ListA = new List<ItemModel>();
List<ItemModel> ListB = new List<ItemModel>();
List<ItemModel> ListResult = new List<ItemModel>();
ListResult = ListA.Distinct(new ItemModelComparer()).ToList();//去重
ListResult = ListA.Except(ListB, new ItemModelComparer()).ToList();//差集
ListResult = ListA.Union(ListB, new ItemModelComparer()).ToList(); //并集
ListResult = ListA.Intersect(ListB, new ItemModelComparer()).ToList();//交集
2、 join的用法
若出现两个List,想用Linq进行查询。则可以使用如下的方式
int tempSatisfiedConditionCount = (from r1 in whiteList
join r2 in args.DiagList on r1.DiagCode equals r2.DiagCode
select r1).Count();
多条件的join
//多条件的联合查核
List<DiagControlModel> whiteDiagList = (from r1 in diagControlList
where r1.ControlRelation == 1
join r2 in args.DiagList on new { code = r1.DiagCode, name = r1.DiagName }
equals new{code=r2.DiagCode,name=r2.DiagName}
select r1).ToList<DiagControlModel>();
另外,join还可以用于左连接/右连接
var LeftJoin = from emp in ListOfEmployees
join dept in ListOfDepartment
on emp.DeptID equals dept.ID into JoinedEmpDept
from dept in JoinedEmpDept.DefaultIfEmpty()
select new
{
EmployeeName = emp.Name,
DepartmentName = dept != null ? dept.Name : null
};
3、let用法
let是一个在linq中定义局部变量
1、可以有多个let子句
2、let后的变量无需声明类型
参见下例:
var query = from a in list
let b = a.Name.Split('-')
let c=a.Age
where b[0] =="zhangs" & c>21
select a;
4、分组
常用的分组用法
var linqtest = 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
};
略微复杂点:
var dataList= (from r in drugLabelList
group r by new
{
r.OrderNo,
r.PatientID,
r.PatientName
} into q
let drugAmount = q.Sum(t => Convert.ToInt32(t.ChargeAmount))
where drugAmount >= 0
select new PrintDrugLabelModel
{
OrderNo = q.Key.OrderNo,
PatientID = q.Key.PatientID,
PatientName = q.Key.PatientName,
ChargeAmount = ""+drugAmount
}).ToList<PrintDrugLabelModel>();
//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"; //多字段 var result = (from item in data group item by new { item.Name, item.Type } into items select new { items.Key.Name, items.Key.Type, Cnt = items.Count() }).ToList(); var s = data.GroupBy(p => new { p.Type, p.Name }).Select(p=>new { p.Key.Type, p.Key.Name, cnt=p.Count() }).ToList();
5、简单的函数计算
var linqtest = (from r in db.Am_recProScheme
select r).Sum(p => p.rpId);
6、排序order by desc/asc
var linqtest = (from r in db.Am_recProScheme
where r.rpId > 10
orderby r.rpId descending //倒序
// orderby r.rpId, r.rpname descending //多条件的倒序(与SQL语句中的相同)
// orderby r.rpId ascending //正序
select r);
7、top(1)
//如果取最后一个可以按倒叙排列再取值
var linqtest = (from r in db.Am_recProScheme
select r).FirstOrDefault();
8、跳过前面多少条数据取余下的数据
var linqtest = (from r in db.Am_recProScheme
where r.rpId > 10
orderby r.rpId descending
select r).Skip(10).Take(10); //取第11条到第20条数据
9、包含
//可以使用List、Array、string的Contains()方法进行判断
var linqtest = (from r in db.Am_recProScheme
where r.SortsText.Contains("张")
select r);
10、连接查询
var linqtest = (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);
11、使用linq查询DataTable
//遍历DataTable,将其中的数据对应到ClientStruct中:
List<ClientStruct> list = (from x in dtTable.AsEnumerable()
orderby x.Field<string>("") descending
where x.Field<string>("ErrorType") == "漏孔"
select new ClientStruct
{
ID = x.Field<string>(cs.ID),
Name = x.Field<string>(cs.Name),
Company = x.Field<string>(cs.Company),
CreatedDate = x.Field<string>(cs.CreatedDate)
}).ToList<ClientStruct>();
12、linq中列传行操作(Aggregate的使用)—2022-3-4
解决分组又聚合的问题。
后台数据存储的样式是:
希望实现:
即:实现分组,并且能将诊断进行聚合(列转行)
linq的写法如下:
var data_list = (from r in temp_result_list
group r by new
{
r.DrugCode,
r.VisitType
} into q
select q.Aggregate(temp_result_list[0],(workingSentence, next) => new DiagControlModel
{
DrugCode = q.Key.DrugCode,
VisitType = q.Key.VisitType,
DiagInfoStr = workingSentence.DiagInfoStr + ";" + next.DiagName
})).ToList<DiagControlModel>();
13.分页数据查询
//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";
14.sql中的In
//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)";
15.多条件联合
这样写会报错,原因是名称不一样
new { 存货申请.cVouch_id, 存货申请.ccode, 存货申请.inid } equals
new { OutAndInDonees.CVouch_Id, OutAndInDonees.MItemCode, OutAndInDonees.I_id }
修改如下:
on new { cVouch_id=存货申请.cVouch_id, ccode= 存货申请.ccode , 存货申请.inid } equals
new { cVouch_id= OutAndInDonees.CVouch_Id, ccode=OutAndInDonees.MItemCode, inid= OutAndInDonees.I_id }
16.什么是多表连接查询
一:编写多表查询语句–内连接
对应SQL语句:
select * from Person join Telephone on Person.Id = Telephone.PersonId
第一种方式:LINQ语法
public List<Twotable> GetTwo()
{
var query = from a in _entityRepository.GetAll()
join b in _TelRepository.GetAll()
on a.Id equals b.PersonId
select new Twotable{
Name=a.Name,
Telephone=b.PhoneNumber
};
return query.ToList();
}
第二种方式:Lambda语法
public List<Twotable> GetTwo()
{
var query = _entityRepository.GetAll()
.Join(
_TelRepository.GetAll(),
top => top.Id,
art => art.PersonId,
(top, art) => new Twotable
{
Name = top.Name,
Telephone = art.PhoneNumber
});
return query.ToList();
}
二:编写多表连接查询–左右连接
- 左连接的概念:
对应SQL语句:
select * from Person left join Telephone on Person.Id = Telephone.PersonId
方法1:LINQ语法
var leftOuterJoin = from a in _entityRepository.GetAll()
join b in _TelRepository.GetAll()
on a.Id equals b.PersonId
into cls from c in cls.DefaultIfEmpty()
select new Twotable
{
Name = a.Name,
Telephone = c.PhoneNumber
};
方法2:Lambda语法
var leftOuterJoin = _entityRepository.GetAll()
.GroupJoin(
_TelRepository.GetAll(),
top => top.Id,
art => art.PersonId,
(top, art) => new Twotable
{
Id = top.Id,
Name = top.Name,
Telephone = art.FirstOrDefault(x => x.PersonId == top.Id).PhoneNumber
}).Select(o => o);
- 右连接的概念:
对应SQL语句:
select * from Person right join Telephone on Person.Id = Telephone.PersonId
三:编写多表连接查询—全连接
全连接的概念
对应SQL语句
select * from Person full outer join Telephone on Person.Id = Telephone.PersonId
使用全连接:(合并左右连接就可以了)
//右连接
var rightOuterJoin = from b in _TelRepository.GetAll()
join a in _entityRepository.GetAll()
on b.PersonId equals a.Id
into cls
from c in cls.DefaultIfEmpty()
select new Twotable
{
Id = c.Id,
Name = c.Name,
Telephone = b.PhoneNumber
};
//左连接
var leftOuterJoin = from a in _entityRepository.GetAll()
join b in _TelRepository.GetAll()
on a.Id equals b.PersonId
into cls from c in cls.DefaultIfEmpty()
select new Twotable
{
Name = a.Name,
Telephone = c.PhoneNumber
};
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);
或者
番外:
如果想 3表 或 4表 连接,那就和SQL语句一样在下面加 join就好了
var fullOuterJoin = leftOuterJoin.Concat(rightOuterJoin);
var query = from b in _TelRepository.GetAll()
join a in _entityRepository.GetAll()
on b.PersonId equals a.Id
into cls
from c in cls.DefaultIfEmpty()
join d in _userRepository.GetAll()
on c.Id equals d.Id
from e in cls.DefaultIfEmpty()
select new Twotable
{
Id = c.Id,
//Name = c.Name,
Name =e.Name,
Telephone = b.PhoneNumber
};
create proc *****
@GoodsId int,
@Number int,
@StockPrice money,
@SupplierId int,
@EmpId int,
@StockUnit varchar(50),
@StockDate datetime,
@TotalMoney money ,
@ActMoney money ,
@baseId int,
@Description nvarchar(255)
as
declare @error int =0 --事务中操作的错误记录
--开启事务
begin transaction
--实现进货信息的添加
insert into StockInfo values(@GoodsId, @Number, @StockPrice, @SupplierId, @EmpId, @StockUnit, @StockDate, @TotalMoney, @ActMoney,DEFAULT,@Description, @baseId)
set @error+=@@ERROR --记录有可能产生的错误号
--获取当前进货信息的标识列
--判断当前商品有没有进货记录
if exists (select * from dbo.InventoryInfo where goodid=@GoodsId) --说明记录存在,直接修改库存数量
begin
update dbo.InventoryInfo set GNumber=GNumber+@Number,TotalMoney+=@TotalMoney where goodid=@GoodsId
set @error+=@@ERROR --记录有可能产生的错误号
end
else --这个商品从来没有过进货记录,那么就应该添加新的存在信息
begin
declare @GWarningNum int --此商品的预警数量
--获取预警数量
set @GWarningNum=(select WaringNum from dbo.GoodsInfo where GId=@GoodsId)
insert into dbo.InventoryInfo values(@GoodsId,@Number,@baseId,@GWarningNum,@TotalMoney,'第一次进货',default)
set @error+=@@ERROR --记录有可能产生的错误号
end
--判断事务的提交或者回滚
if(@error<>0)
begin
rollback transaction
return -1 --设置操作结果错误标识
end
else
begin
commit transaction
return 1 --操作成功的标识
end
go