程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> .NET深入實戰系列—Linq to Sql進階,linqsql

.NET深入實戰系列—Linq to Sql進階,linqsql

編輯:C#入門知識

.NET深入實戰系列—Linq to Sql進階,linqsql


最近在寫代碼的過程中用到了Linq查詢,在查找資料的過程中發現網上的資料千奇百怪,於是自己整理了一些關於Linq中容易讓人困惑的地方。

本文全部代碼基於:UserInfo與Class兩個表,其中Class中的UserId與UserInfo中的Id對應

from user in UserInfo join c in Classes on user.Id equals c.UserId select new { user.UserName, user.Id, c.ClassName }

查詢結果

SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName] FROM [UserInfo] AS [t0] INNER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId]

左聯查詢

左聯應該是聯合查詢中使用頻率最高的查詢。它以左表為准,進行聯合查詢。如果右表中不存在對應的結果,則置空。(注意:在Linq中是不存在右聯連的說法,因為右聯無非是把左邊的表移動到右邊,查詢的結果與左聯是一樣的)

from user in UserInfo  
join c in Classes on user.Id equals c.UserId into temp  
from c in temp.DefaultIfEmpty()  
select new  
{  
     user.UserName,  
     user.Id,  
     c.ClassName  
}  

查詢結果

SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName] AS [ClassName] FROM [UserInfo] AS [t0] LEFT OUTER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId]

!注意一下左聯那個【temp】,它其實是一個IEnumerable集合。所以我們可以得到到左聯的另一種結果:

from user in UserInfo
join c in Classes on user.Id equals c.UserId into temp
select new
{
	user,
	temp
}

查詢結果(為了更明確表達集合,在Class表裡特別加了一條記錄,所以class那邊共有3條)

SELECT t0.*, [t1].[Id] AS [Id2], t1.*, ( SELECT COUNT(*) FROM [Class] AS [t2] WHERE [t0].[Id] = [t2].[UserId] ) AS [value] FROM [UserInfo] AS [t0] LEFT OUTER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId]

全聯接

全聯連是得到兩個表的交叉結果(在SQL中稱為cross join),這種聯連方式得到的結果在沒有過濾條件的情況下,基本沒什麼用。看看即可,代碼如下:

 from user in UserInfo
 from c in Classes
 select new
 {
     user.UserName,
     user.Id,
	 c.ClassName
 }

查詢結果

SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName] FROM [UserInfo] AS [t0], [Class] AS [t1]

合並(Union)

這種查詢其實也很少用,但在某些變態業務需求下會非常有用,注意查詢的結果。它是合並兩個表相同列數的結果,並且如果結果中有相同的行,那麼只取一行記錄。

(
	from userinfo in UserInfo
	select new {
	  Id = (System.Int32?)userinfo.Id,
	  Name = userinfo.UserName
	}
).Union
(
	from c in Classes
	  select new {
	  Id = (System.Int32?)c.UserId,
	  Name = c.ClassName
	}
)

查詢結果

SELECT [t0].[Id] AS [value], [t0].[UserName] FROM [UserInfo] AS [t0] UNION SELECT [t1].[UserId] AS [value], [t1].[ClassName] FROM [Class] AS [t1]

Linq 分組查詢

分組查詢(group by)也是我們在實際項目中一個常用的操作,查詢操作如下:

from c in Classes
group c by c.UserId into temp
select temp

查詢結果

var result = from c in _context.Classes group c by c.UserId into temp select temp; foreach (var c in result) { Console.WriteLine(c.Key); foreach (var citem in c) { Console.WriteLine(citem.ClassName); } }

實體增加字段處理

我在本文例子中的UserInfo實體類如下:

 public partial class UserInfo
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public string UserType { get; set; }
        public int Money { get; set; }
    }

現在我想在該實體中類中添加一個屬性。為了保持原實體類的純潔。我添加一個新的partial類:

public partial class UserInfo
    {
        /// <summary>
        /// 測試擴展屬性
        /// </summary>
        public string UserExt
        {
            get { return UserName + ":" + UserType; }
        }
    }

然後我們用EF訪問一下,發現是可以訪問的:

from user in _context.UserInfoes select new { user.Id, user.UserExt };

會發現編譯是沒有問題的。但運行時會出現下面異常:

from user in _context.UserInfoes.ToList() select new { user.Id, user.UserExt };

即先執行ToList(),提前讓linq進行執行,生成UserInfo集合,這樣就可以正常訪問UserExt了。別看這個小小的改動。在多表聯查過濾字段的情況下,你會體會到無盡的妙處!

你可能會想到一個問題,如果我再加一個完整的屬性會出現什麼情況?

 public partial class UserInfo
    {
        public string UserExt
        {
            get { return UserName + ":" + UserType; }
        }
        //新增一個完整的屬性
        public string UserExt2 { get; set; }
    }

上面的UserExt2是我們新加入的一個屬性,現在我們來執行一下查詢。我想真正去研究過Linq的人肯定知道結果了。

this.Ignore(t => t.UserExt2);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved