zoukankan      html  css  js  c++  java
  • Linq中使用Left Join

    use Test
    Create table Student(
    ID int identity(1,1) primary key,
    [Name] nvarchar(50) not null
    )
    
    Create Table Book(
    ID int identity(1,1) primary key,
    [Name] nvarchar(50)not null,
    StudentID int not null
    )
    
    insert into Student values('张三')
    insert into Student values('李四')
    insert into Student values('王五')
    select * from student
    
    --张三借的书
    insert into Book values('红楼',1)
    insert into Book values('大话红楼',1)
    
    --李四借的书
    insert into Book values('三国',2)
    
    --王五没借书
    
    --一本错误的记录
    insert into Book values('错误时怎样练成的',111)
    
    --左连接
    select s.name,b.name from student as s
    left join Book as b on s.id=b.studentid
    
    --右连接
    select s.name,b.name from student as s
    right join Book as b on s.id=b.studentid

    要用Linq实现左连接,写法如下

    DataClasses1DataContext db = new DataClasses1DataContext();
                var leftJoinSql = from student in db.Student
                                  join book in db.Book on student.ID equals book.StudentID into temp
                                  from tt in temp.DefaultIfEmpty()
                                  select new
                                  {
                                       sname= student.Name,
                                       bname = tt==null?"":tt.Name//这里主要第二个集合有可能为空。需要判断
                                  };

    用Linq实现右连接,写法如下

    DataClasses1DataContext db=new DataClasses1DataContext();
                var rightJoinSql = from book in db.Book
                                   join stu in db.Student on book.StudentID equals stu.ID into joinTemp
                                   from tmp in joinTemp.DefaultIfEmpty()
                                   select new { 
                                   sname=tmp==null?"":tmp.Name,
                                   bname=book.Name
    
                                   };

    使用LINQ联合查询多表结果集的返回

    首先,我们先来了解一些知识点。 
    
    1.匿名类型的传递 
    
           static void Main(string[] args) 
            { 
                var User = GetAnonymous().Cast(new { UserName = "", LastLoginIp = "" }); 
                Console.Write(User.UserName);   
            } 
    
            static object GetAnonymous() 
            { 
                var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" }; 
                return User; 
            } 
    
    当我们定义一个匿名类型,只能通过object类型传递,传递后编译器将无法获悉匿名类型的实际类型。 
    
    这行可以通过Cast扩展方法来进行强制转换。以下是Cast方法的原型。 
    
            public static T Cast<T>(this object o, T t) 
            { 
                return (T)o; 
            } 
    
    2.如何生成匿名类型的List? 
    
               var User = GetAnonymous().Cast(new { UserName = "", LastLoginIp = "" });  
               var list = new List<???>(); 
    
    原理和上面一致。 
                var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" }; 
                var list = User.MakeList(); 
                list.Add(User); 
                Console.Write(list[0].UserName); 
    我们再来看看MakeList()方法: 
    
            public static List<T> MakeList<T>(this T t) 
            { 
                return new List<T>(); 
            } 
    
    当然,你可能想到上面的方法还不够完美,需要在List中Add一个User,于是有了下面的方法: 
            public static List<T> MakeList<T>(this T t,params T[] items) 
            { 
                return new List<T>(items); 
            } 
    这时调用的时候可以写成: 
                var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" }; 
                var list = User.MakeList(User); 
                Console.Write(list[0].UserName); 
    这回我们切入正题,来了解一下LINQ中是怎样多表查询的。 
    
        var q = 
        from p in db.Products 
        where p.Supplier.Country == "USA" && p.UnitsInStock == 0 
        select p; 
    
    更多内容,请参考:博客园 - 李永京- LINQ体验(6)——LINQ to SQL语句之Join和Order By 
    
    以上的查询是两个有关系的表,并且返回的只是一个表的内容, 
    这种情况下可以在数据层中返回强类型的List。如: 
    
    public List<Products> SelectProducts() 
    { 
          var q = 
          from p in db.Products 
          where p.Supplier.Country == "USA" && p.UnitsInStock == 0 
          select p; 
          return q.ToList<Products>; 
    } 
    
    
    如果返回的结果集是两个以上表的时候,那该如何传递呢? 
    
    聪明的你一定想到了,如果返回的是单行数据的结果集就可以我们前面提到的 
    使用 匿名类型的传递 得到我们需要的结果. 
    public object SelectProducts() 
    { 
          var q = 
          from p in db.Products 
          where p.Supplier.Country == "USA" && p.UnitsInStock == 0 
          select new {p.UnitsInStock,p.Supplier.Sid}; 
          var result = q.Single(); 
          return result; 
    } 
    但这个前提是业务逻辑层需要知道数据层的匿名类型中的具体类型。 
    这样分层的意义也就不大了。这并不是我们想要的。 
    而且返回多行数据的结果集时用 匿名的List类型 的方法经实验也失败了。 
    这就意味着本文开篇的两种传递匿名类型的方法都行不通。 
    
    方法一: 
    自定义与返回类型相同结构的类, 
            public class CustomQuery 
            { 
                public uint UnitsInStock { get; set; } 
                public int Sid { get; set; } 
            } 
    这样在查询结果为多个表的结果集时,就可以解决了。 
    由于需要知道返回的匿名类型,除了不符合多层以外,还需要额外定义一个类。 
    但这样确时可以使用强类型返回我们所需要的结果。 
    
    方法二: 
    使用System.Func委托 (参考:Returning var from a method in C# 3.0) 
    
    数据层: 
    public IEnumerable<TProjection> GetCustomersWithOrders<TProjection>(Func<Customer, IEnumerable<Order>, TProjection> projection) { 
        return from customer in _customers 
               let customerOrders = from order in _orders 
                                    where order.CustomerID = customer.ID 
               select projection(customer, customerOrders); 
    } 
    
    业务逻辑层: 
    var results = GetCustomersWithOrders((customer, orders) => 
    new { 
                     Name = customer.Name, 
                     OrderCount = orders.Count() 
          }); 
    这样返回的结果在业务逻辑层里仍然是真正的匿名类型,可以直接使用了。 
    
    方法三: 
    
    使用存储过程或视图。
  • 相关阅读:
    2020杭电多校第二场 1006.The Oculus
    2020杭电多校第一场 1005.Fibonacci Sum
    数论——中国剩余定理
    数论——线性同余方程
    数论——乘法逆元
    数论——裴蜀定理
    javascript预解析和作用域
    数组的排序..........加深难度
    值类型和引用类型
    js中的==和===
  • 原文地址:https://www.cnblogs.com/hnsongbiao/p/4474110.html
Copyright © 2011-2022 走看看