LINQ to SQL
首先创建LINQ to SQL对象模型 在“服务资源管理器中添加要连接的表”,将其拖放在***.dbml设计界面中。
测试程序
DataClassesDataContext DC = new DataClassesDataContext();//创建数据上下文类的实例 var query = from item in DC.WarehouseInfo where item.Area >= 100//使用LINQ查询面积大于100平的仓库 orderby item.ShortName//按仓库名称排序 select item; dataGridView1.DataSource = query.ToList();//将查询结果集绑定到dataGridView1
http://kb.cnblogs.com/page/70851/
取得数据库Gateway
要操作数据库,我们首先要获得一个DataContext对象,这个对象相当于一个数据库的Gateway,所有的操作都是通过它进行的。这个对象的名字是“LINQ to SQL Classes文件名+‘DataContext’”,这里,就是DataClassesDataContext了。它和普通对象一样,直接实例化就行了。在Demo里我将它实例化为一个静态变量。
取得DataContext对象后,每个数据表就会映射到其一个集合属性,例如Category表映射到dataContext.Categories,这是一个集合属性,每一个元素是一个实体类,代表此表中的一条记录。实体类名和表名相同。实体类的字段自然就映射到对应表的字段。
还有一点需要注意,数据库中的一对多关系,在Linq to Sql生成代码时会自动表示到类结构中。并且,这种关联是双向的。例如,Category与Bulletin的一对多关系,到了类结构中,反映成如下形式:在Category类中,有一个名为Bulletins的集合属性,内容是所有属于此Category的Bulletin对象的引用。而在Bulletin类中,也会有个Category1属性(由于Category这个名字被我们用了,所以,这个关联属性自动加了个“1”),其内容是此Bulletin所属Category对象的引用。
Insert操作
Insert用于向数据库添加记录。一般情况下,使用“DataContext.表映射集合.InsertOnSubmit(实体类)”的方式就可以完成Insert操作。不过这里要注意一点,由于Linq to Sql使用了“Unit of Work”模式,所以,对数据库的操作不会立即提交到数据库,而要调用DataContext的SubmitChanges方法,所有改动才会被提交到数据库。
Delete操作
Delete操作用于从数据库中删除记录。表映射集合的DeleteOnSubmit方法可以实现这个操作。这个方法需要一个参数,就是要删除的实体类,这里不能直接传个ID去删除,要首先通过ID找到相应实体类,传给DeleteOnSubmit再删除。当然最后不要忘了SubmitChanges。
Update操作
Update操作用于更新数据库中某已存在记录的信息。在Linq to Sql中,Update操作就是首先加载相应的实体类,修改其相应字段后,SubmitChanges就可以了。
Select操作
Select操作用于从数据库中返回指定的记录。在Linq to Sql中,查询结果都是以实体类或实体类集合的方式返回的。其中实体类集合并不是List,如果想转为List,只需在返回结果上调用ToList方法即可。
如果是查询单一记录,建议使用表映射集合的Single方法。至于查询参数,建议采用lambda表达式。如果你对lambda表达式不熟,可以参考这里http://msdn.microsoft.com/zh-cn/library/bb397687.aspx
获取与Not Exists等价的语句
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 //列出库存中从来没有销售过的商品 var query = from sto in dc.V_StoreInfo //where子句中应用了子查询 where !(from sal in dc.V_SaleInfo select sal.ProductCode).Contains(sto.ProductCode) select new { 仓库 = sto.WareHouseName, 商品名称 = sto.ProductName, 数量 = sto.Quantity, 单价 = sto.Price, 金额 = sto.Amount }; dataGridView1.DataSource = query;//将查询结果绑定到dataGridView1
按多个字段降序排列数据表
DataClassesDataContext dc =new DataClassesDataContext();//创建数据上下文类的实例 //按商品分类、计量单位降序排序 var query = from item in dc.ProductInfo orderby item.ProductType descending, item.Unit descending select item; dataGridView1.DataSource = query;//将查询结果集绑定到dataGridView1
关联查询多表数据
join子句使用特殊的关键字equals关键字比较指定的键是否相等
DataClassesDataContext dc = new DataClassesDataContext();//创建LINQ对象 var query = from sc in dc.SaleContent//销售主表 join sd in dc.SaleDetail on sc.SaleBillCode equals sd.SaleBillCode//按销售单据号关联销售主从表 join pi in dc.ProductInfo on sd.ProductCode equals pi.ProductCode//按商品代码关联商品信息表 join ei in dc.EmployeeInfo on sc.SaleMan equals ei.EmployeeCode//按人员代码关联员工表 join wi in dc.WarehouseInfo on sc.WareHouse equals wi.WareHouseCode//按仓库代码关联仓库信息表 join ci in dc.ClientInfo on sc.ClientCode equals ci.ClientCode//按客户代码关联客户信息表 select new { ID = sc.ID, SaleBillCode = sc.SaleBillCode,//销售单据号 SaleMan = ei.Name,//从员工表取销售员名称 SaleDate = sc.SaleDate,//销售日期 Provider = ci.ShortName,//从客户表取购买单位名称 WareHouse = wi.ShortName,//从仓库表取仓库名称 ProductCode = pi.ProductCode,//从商品信息表取商品代码 ProductName = pi.ShortName,//商品名称 Quantity = sd.Quantity,//数量 Price = sd.Price,//单价 Amount = sd.Quantity * sd.Price,//金额 GrossProfit = sd.Quantity * (sd.Price - sd.Cost)//毛利=销售金额-商品成本 }; dataGridView1.DataSource = query;//将查询的结果集绑定到dataGridView1
按照多个条件分组
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 var query = from sto in dc.V_StoreInfo//查询库存表 group sto by new { sto.WarehouseCode, sto.ProductCode } into g//按仓库代码、商品代码分组 select new { 仓库代码 = g.Key.WarehouseCode, 仓库名称 = g.Max(itm => itm.WareHouseName), 商品代码 = g.Key.ProductCode, 商品名称 = g.Max(itm => itm.ProductName), 库存数量 = g.Sum(itm => itm.Quantity) }; dataGridView1.DataSource = query;//将分组的结果集绑定到dataGridView1
实现动态查询语法
private void Frm_Main_Load(object sender, EventArgs e) { //填充仓库下拉列表框 var WareHouseQuery = dc.WarehouseInfo.Select(itm => new { itm.WareHouseCode, itm.WareHouseName }); comboBox1.DataSource = WareHouseQuery; comboBox1.DisplayMember = "WareHouseName"; } private void button1_Click(object sender, EventArgs e) { if (comboBox1.SelectedIndex > -1)//仓库下拉列表不为空 { if (textBox1.Text.Trim() != "")//商品助记码文本框不为空 { //调用通用查询方法 var query = ConditionQuery<V_StoreInfo>(dc.V_StoreInfo, itm => itm.WareHouseName == comboBox1.Text && itm.HelpCode.StartsWith(textBox1.Text)); dataGridView1.DataSource = query.ToList();//将查询结果绑定到dataGridView1 } else//商品助记码文本框为空 { var query = ConditionQuery<V_StoreInfo>(dc.V_StoreInfo, itm => itm.WareHouseName == comboBox1.Text); dataGridView1.DataSource = query.ToList();//将查询结果绑定到dataGridView1 } } } //通用查询方法 public IEnumerable<TSource> ConditionQuery<TSource>(IEnumerable<TSource> source, Func<TSource, bool> condition) { return source.Where(condition); }
public static IEnumerable<TSource>Where<TSource>(this IEnumerable<TSource>source,Func<TSource,bool>predicate)
Tsource:source中的元素的类型 source:被筛选的数据源 predicate:System.Func<TSource,Boolean>类型,用于测试每个元素是否满足条件的函数
返回值:一个IEnumerable<T>,包含数据源中满足条件的元素
List<int>ints=new List<int>{0,1,2,3,4,5,6,7,8,9}; var query=ConditionQuery<int>(ints,itm=>itm%2==0); foreach(var item inquery) { label1.Text=item.ToString(); }
Count操作:计算元素序列中元素的数量或者是计算满足指定条件的元素的数量
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 //统计每种商品的销售次数 var query = from det in dc.V_SaleDetail group det by det.ProductCode into g//按商品代码分组 select new { 商品代码 = g.Key, 商品名称 = g.Max(itm => itm.ProductName), 销售次数 = g.Count()//使用Count方法统计销售次数 等价于销售次数=g.LongCount()
}; dataGridView1.DataSource = query;//将查询结果集绑定到dataGridView1
Max操作Min操作:计算序列中元素的最大值
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 //统计每种商品的销售总额 var query = from det in dc.V_SaleDetail group det by det.ProductCode into g//按商品代码分组 select new { 商品代码 = g.Key, 商品名称 = g.Max(itm => itm.ProductName), 商品名称=g.Min(itm=>itm.ProductName),
销售总额 = g.Sum(itm => itm.amount),//合计每种商品的销售总额 商品均价=g.Average(itm=>itm.Price)
}; dataGridView1.DataSource = query;//将查询结果绑定到dataGridView1
Aggregate操作 统计月销售额:用于对集合中元素进行自定义的聚合计算
DataClassesDataContext dc = new DataClassesDataContext();//创建LINQ对象 //将销售商品明细表中的金额字段值取出,并转换为数组 double[] amountArray = dc.V_SaleDetail.Select(itm => itm.amount).ToArray<double>(); double amountSum = amountArray.Aggregate((a, b) => a + b);//计算商品销售总额 label1.Text="销售总额是:" + amountSum.ToString("#,##0.00");//显示销售总额
Distinct去除重复操作:将数据源中重复的数据元素去掉
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 var query1 = dc.V_SaleReturnInfo.Select(itm => new { 商品代码 = itm.ProductCode, 商品名称 = itm.ProductName });//查找指定商品 label1.Text="全部的商品返货记录如下\n"; foreach (var item in query1) { label1.Text+=item + "\n"; } var query2 = dc.V_SaleReturnInfo.Select(itm => new { 商品代码 = itm.ProductCode, 商品名称 = itm.ProductName }).Distinct();//去除重复记录 label1.Text += "将返货记录中重复的商品去除\n"; foreach (var item in query2) { label1.Text+=item + "\n"; }
差集操作Except:计算两个集合中的差集,去掉一个集合中在另一个集合中存在的元素
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 var saleInfo = dc.V_SaleInfo.Select(itm => new { itm.ProductCode, itm.ProductName });//销售信息 var saleRetu = dc.V_SaleReturnInfo.Select(itm => new { itm.ProductCode, itm.ProductName });//销售返货 var query = saleInfo.Except(saleRetu);//取差集 dataGridView1.DataSource = query;//将查询的结果集绑定到dataGridView1
Intersect交集操作:用来计算两个集合的交集
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 var saleInfo = from si in dc.V_SaleInfo//销售信息 select new { 商品代码 = si.ProductCode, 商品名称 = si.ProductName }; var saleRetu = from sr in dc.V_SaleReturnInfo//销售返货 select new { 商品代码 = sr.ProductCode, 商品名称 = sr.ProductName }; var query = saleInfo.Intersect(saleRetu);//取交集 dataGridView1.DataSource = query;//将查询的结果集绑定到dataGridView1
Union并集操作
DataClassesDataContext dc = new DataClassesDataContext();//创建数据上下文类的实例 var saleInfo = from si in dc.V_SaleInfo//销售信息 select new { si.ProductCode, si.ProductName, si.Quantity }; var saleRetu = from sr in dc.V_SaleReturnInfo//销售返货 select new { sr.ProductCode, sr.ProductName, Quantity = sr.Quantity * (-1) }; var sale2 = saleInfo.Union(saleRetu);//将销售信息和销售返货合并在一起 var query = from item in sale2//按商品代码和商品名称分组合计销售数量 group item by new { item.ProductCode, item.ProductName } into g select new { 商品代码 = g.Key.ProductCode, 商品名称 = g.Key.ProductName, 销售总数 = g.Sum(itm => itm.Quantity) }; dataGridView1.DataSource = query;//将查询的结果集绑定到dataGridView1
LINQ查询语句必须经过编译后才能执行,对于那些根据界面输入需要制定灵活的查询来说,这种方式显得不太灵活。为了实现这个需求,在Linq的数据上下文类(DataContext)中,提供了直接执行SQL查询的方法。
LINQ中判断数据库是否存在
string conStr = "Data Source=WIN-GI7E47AND9R\\LS;Database=db_TomeTwo;UID=sa;Pwd=;";//定义数据库连接字符串 DataClassesDataContext dc = new DataClassesDataContext(conStr);//创建数据上下文类的实例 if (dc.DatabaseExists() == true)//如果该数据库存在 { label1.Text=dc.Connection.Database + "数据库已经存在!"; } else { label1.Text = dc.Connection.Database + "数据库不存在!"; }
直接执行SQL操作
DataClassesDataContext dc = new DataClassesDataContext();//创建LINQ对象 private void Frm_Main_Load(object sender, EventArgs e) { //填充仓库下拉列表框 var WareHouseQuery = dc.WarehouseInfo.Select(itm => new { itm.WareHouseCode, itm.WareHouseName }); comboBox1.DataSource = WareHouseQuery;//对comboBox1进行数据绑定 comboBox1.DisplayMember = "WareHouseName";//指定要显示的字段 } private void button1_Click(object sender, EventArgs e) { string sql = "select * from V_StoreInfo where 1=1"; if (comboBox1.SelectedIndex > -1)//仓库下拉列表不为空 { sql += " and WareHouseName = '" + comboBox1.Text + "'"; } if (textBox1.Text.Trim()!= "")//商品助记码文本框不为空 { sql += " and HelpCode like '" + textBox1.Text + "%'"; } var query = dc.ExecuteQuery<V_StoreInfo>(sql);//执行SQL查询 dataGridView1.DataSource = query.ToList();//对dataGridView1进行数据绑定 }
数据绑定 操作
private void button1_Click(object sender, EventArgs e) { if (dc.DatabaseExists() == true) { textBox1.Text = dc.Connection.Database + "数据库存在"; } else { textBox1.Text = dc.Connection.Database + "数据库不存在"; } } private void button2_Click(object sender, EventArgs e) { } private string conStr = "Server=(local);DataBase=db_1;Integrated Security=true"; DataClassesDataContextDataContext dc ; private void Form1_Load(object sender, EventArgs e) { BingInfo(); } private void button3_Click(object sender, EventArgs e) { dc = new DataClassesDataContextDataContext(conStr); Employees emp = new Employees(); emp.EmployeeID = txtEmployeeID.Text.Trim(); emp.Name = txtName.Text.Trim(); emp.Birthday =Convert.ToDateTime(txtBirthday.Text.Trim()); emp.Sex = txtSex.Text == "男" ? true : false; emp.Address = txtAddress.Text.Trim(); emp.Zip = txtZip.Text.Trim(); emp.PhoneNumber = txtPhoneNumber.Text.Trim(); emp.DepartmentID = txtEmployeeID.Text.Trim(); dc.Employees.InsertOnSubmit(emp); dc.SubmitChanges(); BingInfo(); } private void BingInfo() { dc = new DataClassesDataContextDataContext(conStr); var query = from p in dc.Employees select new { 雇员编号 = p.EmployeeID, 姓名 = p.Name, 性别 = p.Sex == true ? "男" : "女", 出生日期 = p.Birthday, 邮编 = p.Zip, 电话号码 = p.PhoneNumber, 部门号 = p.DepartmentID, 家庭住址 = p.Address }; dataGridView1.DataSource = query.ToList(); }
InsertOnSubmit方法用于将处于pending insert状态的实体添加到数据库中,然后通过SubminChanges方法提交对数据库的增删查改操作。
LINQ分页
http://www.cnblogs.com/9527/archive/2007/07/05/807451.html
static IEnumerable<T> GetIenumberable<T>(IEnumerable<T> List,Func<T, bool> FunWhere,Func<T,string> FunOrder, int PageSize, int PageIndex) { var rance = List.Where(FunWhere).OrderByDescending(FunOrder).Select(t => t).Skip((PageIndex - 1) * PageSize).Take(PageSize); return rance; }
使用LINQ技术防止SQL注入式攻击
string name = txtName.Text;//获取用户名 string pwd = txtPwd.Text;//获取密码 //创建LINQ对象 LinqClassDataContext linqDataContext = new LinqClassDataContext(); //创建LINQ查询语句,查询到满足指定用户名和密码的用户 var result = from v in linqDataContext.tb_Login where v.Name == name && v.Pwd == pwd select v; if (result.Count() > 0) { //输出相应信息 MessageBox.Show("登录成功"); } else { MessageBox.Show("登录失败!"); }