Linq操作

LinQ是指集成化查询语言,通过映射将【数据库】内的表名变为C#的类名,将列名作为属性名,将表的关系作为类的成员对象。O--M--R

O-Object对象
R-Relation关系
M-Mapping映射

LinQ包括:LinQ to SQL,针对SQL的查询,它是一个带有可视化的操作界面的ORM工具。

               LinQ to Object,用来实现对内存中集合对象的查询。

               LinQ to DataSet,对强类型化或弱类型化的DataSet或独立的DataTable进行查询。

               LinQ to Entity,对实体框架中EDM定义的实体集合进行查询。

(一)LinQ to SQL

第一步:建立LinQ2SQL类

添加一个新建项,选择LinQ to SQL,将用到的表拖进来。

第二步:实例化上下文对象,基本所有操作都是通过上下文对象来进行的。

MyDBDataContext context = new MyDBDataContext();

第三步:操作

一、增加数据:

1.造一个要添加的数据对象:

Info data = new Info();
data.Code = "p211";
data.Name = "石头";
data.Sex = false;
data.Nation = "N001";
data.Birthday = new DateTime(1990, 1, 2);

2.在上下文中注册上面新造的对象。

context.Info.InsertOnSubmit(data);

3.提交执行

context.SubmitChanges();

  二、删除:

1. 找出要删除的数据

MyDBDataContext context = new MyDBDataContext();
var q = context.Info.Where(p => p.Code == "p003");

2. 删除注册

if (q.Count() > 0)
{
     Info data = q.First();
    //注册
    context.Work.DeleteAllOnSubmit(data.Work);
    context.Family.DeleteAllOnSubmit(data.Family);
    context.Info.DeleteOnSubmit(data);
}

3. 提交执行

context.SubmitChanges();

三、修改:

1. 找出要修改的数据

MyDBDataContext context = new MyDBDataContext();
var q = context.Info.Where(p=>p.Code == "p001");

2. 改,不用注册

if (q.Count() > 0)
{
    Info data = q.First();
    //
    data.Name = "胡生";
    data.Nation = "n001";
    data.Sex = false;
}

3. 提交执行

context.SubmitChanges();

四、查询:

1.查所有

MyDBDataContext context = new MyDBDataContext();
//所有人员
var q = context.Info;
//var q = from p in context.Info select p;
//显示
foreach(Info data in q)
{
    //data.Nation1:当前人员对应的民族对象。
    Console.WriteLine(data.Name+"\t"+data.Nation1.Name);
    //data.Work:当前人员对应的工作记录集合
    foreach (Work work in data.Work)
    {
        Console.WriteLine("\t"+work.Firm+"\t"+work.Depart);
    }
}

2. 根据主键查询(条件查询),默认返回的都是集合。

var q = from p in context.Info where p.Code == "p211" select p;
var q = context.Info.Where(p => p.Code == "p211").Where(p => p.Nation1.Name == "汉族"); //Lambda表达式(最最简化的函数,只有参数和函数体的匿名函数)
var q = context.Info.Where(p => p.Code == "p211" && p.Nation1.Name=="汉族");
var q = context.Info.Where(p => p.Code == "p211"); //默认返回的是集合
if (q.Count() > 0)    //看看集合中是否查出数据来了
{
    Info data = q.First(); //取第一个对象出来
    Console.WriteLine(data.Nation1.Name + data.Name);
}

3. 多条件查询

var q = from p in context.Car where p.Price > 30 && p.Brand=="b002" select p;
var q = context.Car.Where(p => p.Price > 30 && p.Brand == "b002");
var q = context.Car.Where(p => p.Price > 30).Where(p => p.Brand == "b002");
var q = from p in context.Car where p.Price > 30 || p.Brand == "b002" select p;
var q = context.Car.Where(p => p.Price > 30 || p.Brand == "b002");
var result = from e in db.Employees where e.HireDate >= new DateTime(1994, 1, 1) || e.Title.Contains("Manager") select e; //把1994年后雇佣的,或者Title中包含“经理”的员工选出来
//case when
var q = from c in db.Customers selectnew { Name = c.ContactName, Address = new { City = c.City, Region = c.Region == null ? "Unknown" : c.Region } };

4. 模糊查询

var q = from p in context.Car where p.Name.Contains("5") select p; //包含
var q = from p in context.Car where p.Name.StartsWith("奥迪") select p;//开头
var q = from p in context.Car where p.Name.EndsWith("奥迪") select p;//结尾
var q = context.Car.Where(p => p.Name.Contains("5"));//包含
var q = context.Car.Where(p => p.Name.StartsWith("奥迪"));//开头
var q = context.Car.Where(p => p.Name.EndsWith(""));//结尾
var q = from p in context.Car where p.Name.Substring(2, 1) == "5" select p;//第三个字符
var q = context.Car.Where(p => p.Name.Substring(2,1) == "5");//第三个字符是5

5. Distinct查询

var q = (from p in context.Car select p.Brand).Distinct();//去重
var q = context.Car.Select(p=>p.Brand).Distinct();//去重

6. 连接查询——对象之间的关联关系点出来的。INNER JOIN和OUTER JOIN

想用LINQ to SQL直接写联表查询是很麻烦的,不过这也是唯一一个相比直接用SQL来得更麻烦的地方。

var q = context.Car.Where(p => p.Brand1.Productor.Prod_Name=="一汽丰田");

6.1 內连接
     var result = from d in db.Order_Details join o in db.Orders on d.OrderID equals o.OrderID selectnew {d.OrderID, d.ProductID, d.UnitPrice, o.RequiredDate};

翻译为

    SELECT[t0].[OrderID], [t0].[ProductID], [t0].[UnitPrice], [t1].[RequiredDate]FROM[dbo].[Order Details]AS[t0]INNERJOIN[dbo].[Orders]AS[t1]ON[t0].[OrderID]=[t1].[OrderID]

另外一种更紧凑的写法

     var result =from d in db.Order_Details from o in db.Orders.Where(item=>item.OrderID==d.OrderID) select new { d.OrderID, d.ProductID, d.UnitPrice, o.RequiredDate };

翻译为

     SELECT[t0].[OrderID], [t0].[ProductID], [t0].[UnitPrice], [t1].[RequiredDate]FROM[dbo].[Order Details]AS[t0], [dbo].[Orders]AS[t1]WHERE[t1].[OrderID]=[t0].[OrderID]

执行效果一样的

6.2 外连接
     var result = from d in db.Order_Details join o in db.Orders on d.OrderID equals o.OrderID into temp from p in temp.DefaultIfEmpty() selectnew {d.OrderID, d.ProductID, d.UnitPrice, p.RequiredDate};

另一种更紧凑的写法是:

    var result = from d in db.Order_Details from o in db.Orders.Where(item => item.OrderID == d.OrderID).DefaultIfEmpty() selectnew {d.OrderID, d.ProductID, d.UnitPrice, o.RequiredDate };

翻译为

   SELECT[t0].[OrderID], [t0].[ProductID], [t0].[UnitPrice], [t1].[RequiredDate]AS[RequiredDate]FROM[dbo].[Order Details]AS[t0]LEFTOUTERJOIN[dbo].[Orders]AS[t1]ON[t1].[OrderID]=[t0].[OrderID]

7. 去重查询出显示,IEnumerable是集合的根类型

static void Show(IEnumerable<string> q)
{
    foreach (string d in q)
    {
        Console.WriteLine(d);
    }
}

8. 统计查询

MyDBDataContext context = new MyDBDataContext();
//var query = from p in context.Car select p;
var query = context.Car;//查出所有
Console.WriteLine(query.Count());//统计个数
Console.WriteLine(query.Max(p => p.Price));//价格的最大值
Console.WriteLine(query.Min(p => p.Price));//价格的最小值
Console.WriteLine(query.Max(p => p.Price * p.Oil));//价格乘以油耗的最大值
Console.WriteLine(query.Sum(p => p.Price));//价格求和
Console.WriteLine(query.Sum(p => p.Price * p.Oil));//价格乘以油耗之后求和
Console.WriteLine(query.Average(p => p.Price));//价格平均值

var result = db.Products.Select(p => p.UnitPrice).Average();
var result = db.Products.Average(p => p.UnitPrice);
var result = (from p in db.Products select p.UnitPrice).Average();
var result = from p in db.Products group p by p.CategoryID into g select new {
g.Key, Amount = g.Count(),
MaxPrice = g.Max(item => item.UnitPrice),
                                       MinPrice = g.Min(item=>item.UnitPrice),
                                       AveragePrice = g.Average(item=>item.UnitPrice) };

9. 分页查询

//分页
MyDBDataContext context = new MyDBDataContext();
var query = context.Car.Skip(2 * 4).Take(4);//每页4条数据,要查第三页的4条数据,跳过8条取下面4条
Show(query);

10. 排序查询

//排序
MyDBDataContext context = new MyDBDataContext();
//var query = context.Car.OrderBy(p=>p.Price); //升序
var query = context.Car.OrderByDescending(p => p.Price);//降序
Show(query);

11. 集合操作

//集合操作
MyDBDataContext context = new MyDBDataContext();
var query1 = context.Car.Where(p => p.Brand1.Productor.Prod_Name == "一汽丰田");
var query2 = context.Car.Where(p => p.Price > 30);

//交集
var query = query1.Intersect(query2);
//并集
//var query = query1.Union(query2);
//差集
//var query = query1.Except(query2);
//补集
//var query = context.Car.Except(query1);
Show(query);

12.EXISTS

选出没有订单的客户

   var result = from c in db.Customers where !c.Orders.Any() select c;//其实Any还可以带条件参数哦。

13.WHERE IN
查看指定的几个客户的订单

var result = ( from o in db.Orders where ( newstring[] { "AROUT", "BOLID", "FISSA" }) .Contains(o.CustomerID);

14.直接执行SQL语句查询
如果发现查询语句很难写,(或者写出来LINQ会傻乎乎地生成低效的多次执行)可以考虑直接使用SQL语句,但缺点就是失去了编译器检查的功能,并且得自己构建好一个类,用于存放数据(如果此类还没有的话)。

   IEnumerable<Employee> emps = db.ExecuteQuery<Employee>("select * from Employees");

以上是关于LINQ的一些基本用法,LINQ实用起来非常方便,同时功能也很强大,很好用

15.First/FirstOrDefault/Single(是用TOP实现的)
都是取出一条记录,区别是:

First – 至少有一条,否则抛异常
FirstOrDefault – 如果一条都没有,则返回默认值(对象的话默认值就是null)
Single – 有且只有一条,否则抛异常
选出ID为1的雇员:

Employee theveryemp = db.Employees.Single(item => item.EmployeeID == 1);

这个语句会立即执行,如果获取不到或者不止一条,则抛出异常。

16.字符串操作
以下这些LINQ中对字符串操作的部分都会被聪明地转变为相关的SQL语句,而不是使用C#代码来操作。具体会被转换成什么,大家动手试试看。

Location = c.City + ", " + c.Country p.ProductName.Length < 10 c.ContactName.Contains("Anders") c.ContactName.IndexOf("") c.ContactName.StartsWith("Maria") c.ContactName.EndsWith("Anders") p.ProductName.Substring(3); e.HomePhone.Substring(6, 3) == "555" e.LastName.ToUpper() c.CategoryName.ToLower() e.HomePhone.Substring(0, 5).Trim() e.HomePhone.Insert(5, ":") e.HomePhone.Remove(9) e.HomePhone.Remove(0, 6) s.Country.Replace("UK", "United Kingdom")

17.查询条件拼接

客户端在查询的时候往往会附带一些查询条件,例如商品名称模糊查询,日期范围,商品类型范围,当然还有分页等等。我们通常把这些查询条件封装到一个对象中去,然后让服务器来解释这个对象并拼接SQL查询语句。拼接SQL语句是极其容易出错的事情,而且检查起来还比较费劲,因为SQL语句写起来并不像C#代码那样可以自动格式化。如今使用LINQ to SQL这些问题就不存在了。

var q = fromp indb.Products selectp;

if(条件A)

{q=q.Where(p=>p.XXX==A);}

if(条件B)

{q=q.Where(p=>p.YYY!=B);}

if(条件C)

{q=q.Where(p=>p.ZZZ.Contains(C));}

18、自动事务处理

也许你发现了,对于增删改,都是在SubmitChanges的时候执行,而且一次SubmitChanges,能改多个表多条记录,那事务在哪里?其实LINQ to SQL已经自动帮我们封装好事务了,在执行的过程中,一旦有一步失败,操作将会回滚,这个完全不需要我们担心。

19、关于自增的ID字段

按设计惯例,每张表都应该有一个自增的ID字段,对于这个字段,其值总是由数据库自动生成的,所以我们在Insert一行的时候,从来不需要指定其ID。例如,我们查看ProductID的属性列表,有个叫Auto Generated Value的属性,其值为True,即代表这个字段的值是DBMS自动生成的,你不需要指定。

那么我们插入了一条记录之后,我们想取回这个自动生成的ID的值,怎么办呢?按以前的做法是:

select scope_identity()

现在的做法是在SubmitChanges()之后直接通过插入的对象带出这个自动生成的ID的值:

Category newCategory = new Category {CategoryName = "Fruit", Description = "Fruits..."}; db.Categories.InsertOnSubmit(newCategory); db.SubmitChanges(); Console.WriteLine(newCategory.CategoryID);

那现在有这么种情况,我要添加一个订单,同时给这个订单添加若干条明细,怎么办?这个看起来有点难,难在哪里?你要添加明细,你就必须知道主档的ID,但在SubmitChanges之前,你是拿不到主档的ID的;如果你在Insert了主档之后就Submit,那一旦在Insert明细的时候失败,你就无法回滚了。

OK,其实这么想的话还是按照旧的思路,LINQ to SQL是一套ORM,我们应该直接指定其对象的关系,而不是去关心ID的值是多少,这是正确的做法:

Order newOrder = new Order { CustomerID = "ALFKI", ShipAddress = "Shanghai ..." }; Order_Detail newDetail1 = new Order_Detail { Discount = 1.0f, ProductID = 1, Quantity = 1, UnitPrice = 9.0M }; Order_Detail newDetail2 = new Order_Detail { Discount = 0.9f, ProductID = 2, Quantity = 2, UnitPrice = 5.0M }; newOrder.Order_Details.Add(newDetail1); newOrder.Order_Details.Add(newDetail2); db.Orders.InsertOnSubmit(newOrder); db.SubmitChanges();

20、关于默认值

数据库的表中的很多字段都带有默认值,前面提到的自增ID就是一个例子,但大多字段跟ID不同的是:ID是强制的并且一定是DBMS自动分配的,而这些带默认值的字段则不一定强制,并且允许由用户传入值。如果把这些带默认值的字段跟自增ID一样,设置其“Auto Generated Value”属性为True的话,我们就没办法设置它的值了,它的值总是由DBMS自动分配,而事实上,我们想要的结果是:当我没有给值的时候使用默认值,当我有给值的时候,使用我的值。很不幸,LINQ to SQL做不到,我尝试过很多种方法,结果很明确,就是做不到!这也许算是LINQ to SQL的一个缺陷吧。

所以,使用LINQ to SQL的话就把DBMS的默认值忽略掉吧,每次都手工把值传进去好了……

(转)https://www.cnblogs.com/lingxin/p/6084815.html

posted on 2018-06-02 10:25  欢笑一声  阅读(133)  评论(0)    收藏  举报

导航