1. 程式人生 > >Any與All的用法(Entity Framework)

Any與All的用法(Entity Framework)

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。

屬於某個角色的使用者列表(Any的用法)

使用Subsonic,我們有兩種方法獲取屬於某個角色的使用者列表,分別是表關聯和子查詢。

Subsonic的表關聯實現:

// 查詢 X_User 表
SqlQuery q = new Select().From<XUser>().InnerJoin(XRoleUser.UserIdColumn, XUser.IdColumn);
q.Where("1").IsEqualTo("1");

// 在使用者名稱稱中搜索
string searchText = ttbSearchUser.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
	q.And(XUser.NameColumn).ContainsString(searchText);
}

// 過濾選中角色下的所有使用者
object[] values = Grid1.DataKeys[Grid1.SelectedRowIndexArray[0]];
int roleId = Convert.ToInt32(values[0]);
q.And(XRoleUser.RoleIdColumn).IsEqualTo(roleId);


// 在查詢新增之後,排序和分頁之前獲取總記錄數
// Grid1總共有多少條記錄
Grid2.RecordCount = q.GetRecordCount();

// 排列
q.OrderBys.Add(GetSortExpression(Grid2, XUser.Schema));

// 資料庫分頁
q.Paged(Grid2.PageIndex + 1, Grid2.PageSize);
XUserCollection items = q.ExecuteAsCollection<XUserCollection>();

Grid2.DataSource = items;
Grid2.DataBind();

Subsonic的子查詢實現:

// 查詢 X_User 表
SqlQuery q = new Select().From<XUser>();
q.Where("1").IsEqualTo("1");

// 在使用者名稱稱中搜索
string searchText = ttbSearchUser.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
	q.And(XUser.NameColumn).ContainsString(searchText);
}

// 過濾選中角色下的所有使用者
object[] values = Grid1.DataKeys[Grid1.SelectedRowIndexArray[0]];
int roleId = Convert.ToInt32(values[0]);
SqlQuery subQ = new Select(XRoleUser.UserIdColumn).From<XRoleUser>().Where(XRoleUser.RoleIdColumn).IsEqualTo(roleId);

q.And(XUser.IdColumn).In(subQ);


// 在查詢新增之後,排序和分頁之前獲取總記錄數
// Grid1總共有多少條記錄
Grid2.RecordCount = q.GetRecordCount();

// 排列
q.OrderBys.Add(GetSortExpression(Grid2, XUser.Schema));

// 資料庫分頁
q.Paged(Grid2.PageIndex + 1, Grid2.PageSize);
XUserCollection items = q.ExecuteAsCollection<XUserCollection>();

Grid2.DataSource = items;
Grid2.DataBind();

使用Entity Framework就不能從資料庫的角度思考問題,而應該從實體類之間的關係考慮問題,具體的實現:

IQueryable<User> q = DB.Users;
 
// 在使用者名稱稱中搜索
string searchText = ttbSearchUser.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
	q = q.Where(u => u.Name.Contains(searchText));
}

// 過濾選中角色下的所有使用者
object[] values = Grid1.DataKeys[Grid1.SelectedRowIndexArray[0]];
int roleId = Convert.ToInt32(values[0]);
q = q.Where(u => u.Roles.Any(r => r.ID == roleId));

// 在查詢新增之後,排序和分頁之前獲取總記錄數
Grid2.RecordCount = q.Count();

// 排列和分頁
q = SortAndPage<User>(q, Grid2);

Grid2.DataSource = q;
Grid2.DataBind();

這裡用到了 Any 方法,可以這麼理解:檢索一些使用者,只要使用者的任意一個角色是roleId就可以。

來看下生成的SQL語句:

exec sp_executesql N'SELECT TOP (20) 
[Project2].[ID] AS [ID], 
[Project2].[Name] AS [Name], 
[Project2].[Email] AS [Email], 
[Project2].[Password] AS [Password], 
[Project2].[Enabled] AS [Enabled], 
[Project2].[Gender] AS [Gender], 
[Project2].[ChineseName] AS [ChineseName], 
[Project2].[EnglishName] AS [EnglishName], 
[Project2].[Photo] AS [Photo], 
[Project2].[QQ] AS [QQ], 
[Project2].[CompanyEmail] AS [CompanyEmail], 
[Project2].[OfficePhone] AS [OfficePhone], 
[Project2].[OfficePhoneExt] AS [OfficePhoneExt], 
[Project2].[HomePhone] AS [HomePhone], 
[Project2].[CellPhone] AS [CellPhone], 
[Project2].[Address] AS [Address], 
[Project2].[Remark] AS [Remark], 
[Project2].[IdentityCard] AS [IdentityCard], 
[Project2].[Birthday] AS [Birthday], 
[Project2].[TakeOfficeTime] AS [TakeOfficeTime], 
[Project2].[LastLoginTime] AS [LastLoginTime], 
[Project2].[CreateTime] AS [CreateTime], 
[Project2].[DeptID] AS [DeptID]
FROM ( SELECT [Project2].[ID] AS [ID], [Project2].[Name] AS [Name], [Project2].[Email] AS [Email], [Project2].[Password] AS [Password], [Project2].[Enabled] AS [Enabled], [Project2].[Gender] AS [Gender], [Project2].[ChineseName] AS [ChineseName], [Project2].[EnglishName] AS [EnglishName], [Project2].[Photo] AS [Photo], [Project2].[QQ] AS [QQ], [Project2].[CompanyEmail] AS [CompanyEmail], [Project2].[OfficePhone] AS [OfficePhone], [Project2].[OfficePhoneExt] AS [OfficePhoneExt], [Project2].[HomePhone] AS [HomePhone], [Project2].[CellPhone] AS [CellPhone], [Project2].[Address] AS [Address], [Project2].[Remark] AS [Remark], [Project2].[IdentityCard] AS [IdentityCard], [Project2].[Birthday] AS [Birthday], [Project2].[TakeOfficeTime] AS [TakeOfficeTime], [Project2].[LastLoginTime] AS [LastLoginTime], [Project2].[CreateTime] AS [CreateTime], [Project2].[DeptID] AS [DeptID], row_number() OVER (ORDER BY [Project2].[Name] DESC) AS [row_number]
	FROM ( SELECT 
		[Extent1].[ID] AS [ID], 
		[Extent1].[Name] AS [Name], 
		[Extent1].[Email] AS [Email], 
		[Extent1].[Password] AS [Password], 
		[Extent1].[Enabled] AS [Enabled], 
		[Extent1].[Gender] AS [Gender], 
		[Extent1].[ChineseName] AS [ChineseName], 
		[Extent1].[EnglishName] AS [EnglishName], 
		[Extent1].[Photo] AS [Photo], 
		[Extent1].[QQ] AS [QQ], 
		[Extent1].[CompanyEmail] AS [CompanyEmail], 
		[Extent1].[OfficePhone] AS [OfficePhone], 
		[Extent1].[OfficePhoneExt] AS [OfficePhoneExt], 
		[Extent1].[HomePhone] AS [HomePhone], 
		[Extent1].[CellPhone] AS [CellPhone], 
		[Extent1].[Address] AS [Address], 
		[Extent1].[Remark] AS [Remark], 
		[Extent1].[IdentityCard] AS [IdentityCard], 
		[Extent1].[Birthday] AS [Birthday], 
		[Extent1].[TakeOfficeTime] AS [TakeOfficeTime], 
		[Extent1].[LastLoginTime] AS [LastLoginTime], 
		[Extent1].[CreateTime] AS [CreateTime], 
		[Extent1].[DeptID] AS [DeptID]
		FROM [dbo].[Users] AS [Extent1]
		WHERE (N''admin'' <> [Extent1].[Name]) AND ( EXISTS (SELECT 
			1 AS [C1]
			FROM [dbo].[RoleUsers] AS [Extent2]
			WHERE ([Extent1].[ID] = [Extent2].[UserID]) AND ([Extent2].[RoleID] = @p__linq__0)
		))
	)  AS [Project2]
)  AS [Project2]
WHERE [Project2].[row_number] > 0
ORDER BY [Project2].[Name] DESC',N'@p__linq__0 int',@p__linq__0=1
go

EF生成的SQL語句是很複雜,我們來稍微簡化一下(為了看清本質,去掉了排序,過濾以及返回欄位的個數等):

exec sp_executesql N'SELECT [Project2].[ID] AS [ID], [Project2].[Name] AS [Name], [Project2].[Email] AS [Email], [Project2].[Password] AS [Password]
	FROM ( SELECT 
		[Extent1].[ID] AS [ID], 
		[Extent1].[Name] AS [Name], 
		[Extent1].[Email] AS [Email], 
		[Extent1].[Password] AS [Password]
		FROM [dbo].[Users] AS [Extent1]
		WHERE (N''admin'' <> [Extent1].[Name]) AND ( EXISTS (SELECT 
			1 AS [C1]
			FROM [dbo].[RoleUsers] AS [Extent2]
			WHERE ([Extent1].[ID] = [Extent2].[UserID]) AND ([Extent2].[RoleID] = @p__linq__0)
		))
	)  AS [Project2]',N'@p__linq__0 int',@p__linq__0=1
go

進一步簡化:

exec sp_executesql N' SELECT 
		[Extent1].[ID] AS [ID], 
		[Extent1].[Name] AS [Name], 
		[Extent1].[Email] AS [Email], 
		[Extent1].[Password] AS [Password]
		FROM [dbo].[Users] AS [Extent1]
		WHERE (N''admin'' <> [Extent1].[Name]) AND ( EXISTS (SELECT 
			1 AS [C1]
			FROM [dbo].[RoleUsers] AS [Extent2]
			WHERE ([Extent1].[ID] = [Extent2].[UserID]) AND ([Extent2].[RoleID] = @p__linq__0)
		))
	',N'@p__linq__0 int',@p__linq__0=1
go

進一步簡化:

SELECT 
		[Users].[ID] AS [ID], 
		[Users].[Name] AS [Name], 
		[Users].[Email] AS [Email], 
		[Users].[Password] AS [Password]
		FROM [dbo].[Users] AS [Users]
		WHERE EXISTS (SELECT 
			1 AS [C1]
			FROM [dbo].[RoleUsers] AS [RoleUsers]
			WHERE ([Users].[ID] = [RoleUsers].[UserID]) AND ([RoleUsers].[RoleID] = 1)
		)

進一步簡化:

SELECT 
		ID, 
		Name, 
		Email, 
		Password
		FROM Users
		WHERE EXISTS (SELECT 
			1
			FROM RoleUsers
			WHERE (Users.ID = RoleUsers.UserID) AND (RoleUsers.RoleID = 1)
		)	

最終,我們看到了Entity Framework使用子查詢和 EXISTS 關鍵字來完成 Any 的操作。

當然,如果是我們自己寫SQL,可以使用 IN 關鍵字來達到相同的效果:

SELECT 
		ID, 
		Name, 
		Email, 
		Password
		FROM Users
		WHERE ID IN (SELECT 
			UserID
			FROM RoleUsers
			WHERE (Users.ID = RoleUsers.UserID) AND (RoleUsers.RoleID = 1)
		)	

也可以使用關聯查詢達到相同的效果:

SELECT 
		ID, 
		Name, 
		Email, 
		Password
		FROM Users 
		INNER JOIN RoleUsers
		ON (Users.ID = RoleUsers.UserID) AND (RoleUsers.RoleID = 1)

幸運的是,我麼只需要一個 Any 關鍵字就完成了這個稍微複雜的查詢。  

不屬於某個角色的使用者列表(All的用法)

類似的,查詢不屬於某個角色的使用者列表(用來新增使用者到某個角色的UI介面中),使用Subsonic也有兩種方法,我們只看下子查詢的方式:

SqlQuery q = new Select().From<XUser>(); 
q.Where("1").IsEqualTo("1");
 
// 在職務名稱中搜索
string searchText = ttbSearchMessage.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
    q.And(XUser.NameColumn).ContainsString(searchText);
}
 
// 排除已經屬於本角色的使用者
int currentRoleId = GetQueryIntValue("id");
SqlQuery subQ = new Select(XRoleUser.UserIdColumn).From<XRoleUser>().Where(XRoleUser.RoleIdColumn).IsEqualTo(currentRoleId);
 
q.And(XUser.IdColumn).NotIn(subQ);
 
// 在查詢新增之後,排序和分頁之前獲取總記錄數
Grid1.RecordCount = q.GetRecordCount();
 
// 排列
q.OrderBys.Add(GetSortExpression(Grid1, XUser.Schema));
 
// 資料庫分頁
q.Paged(Grid1.PageIndex + 1, Grid1.PageSize);
XUserCollection items = q.ExecuteAsCollection<XUserCollection>();
 
 
Grid1.DataSource = items;
Grid1.DataBind();

使用Entity Framework,我們只需藉助 All 關鍵字就能簡單實現:

IQueryable<User> q = DB.Users;
 
// 在職務名稱中搜索
string searchText = ttbSearchMessage.Text.Trim();
if (!String.IsNullOrEmpty(searchText))
{
    q = q.Where(u => u.Name.Contains(searchText));
}
 
// 排除已經屬於本角色的使用者
int currentRoleId = GetQueryIntValue("id");
q = q.Where(u => u.Roles.All(r => r.ID != currentRoleId));
 
// 在查詢新增之後,排序和分頁之前獲取總記錄數
Grid1.RecordCount = q.Count();
 
// 排列和分頁
q = SortAndPage<User>(q, Grid1);
 
Grid1.DataSource = q;
Grid1.DataBind();

可以簡單的理解:檢索一些使用者,要保證這些使用者的所有角色沒有一個是currentRoleId。

去除分頁和排序後,生成的SQL語句為:

exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[Name] AS [Name], 
[Extent1].[Email] AS [Email], 
[Extent1].[Password] AS [Password], 
[Extent1].[Enabled] AS [Enabled], 
[Extent1].[Gender] AS [Gender], 
[Extent1].[ChineseName] AS [ChineseName], 
[Extent1].[EnglishName] AS [EnglishName], 
[Extent1].[Photo] AS [Photo], 
[Extent1].[QQ] AS [QQ], 
[Extent1].[CompanyEmail] AS [CompanyEmail], 
[Extent1].[OfficePhone] AS [OfficePhone], 
[Extent1].[OfficePhoneExt] AS [OfficePhoneExt], 
[Extent1].[HomePhone] AS [HomePhone], 
[Extent1].[CellPhone] AS [CellPhone], 
[Extent1].[Address] AS [Address], 
[Extent1].[Remark] AS [Remark], 
[Extent1].[IdentityCard] AS [IdentityCard], 
[Extent1].[Birthday] AS [Birthday], 
[Extent1].[TakeOfficeTime] AS [TakeOfficeTime], 
[Extent1].[LastLoginTime] AS [LastLoginTime], 
[Extent1].[CreateTime] AS [CreateTime], 
[Extent1].[DeptID] AS [DeptID]
FROM [dbo].[Users] AS [Extent1]
WHERE  NOT EXISTS (SELECT 
	1 AS [C1]
	FROM [dbo].[RoleUsers] AS [Extent2]
	WHERE ([Extent1].[ID] = [Extent2].[UserID]) AND (([Extent2].[RoleID] = @p__linq__0) OR (CASE WHEN ([Extent2].[RoleID] <> @p__linq__0) THEN cast(1 as bit) WHEN ([Extent2].[RoleID] = @p__linq__0) THEN cast(0 as bit) END IS NULL))
)',N'@p__linq__0 int',@p__linq__0=1
go

最終簡化為:

SELECT 
ID, 
Name, 
Email, 
Password
FROM Users
WHERE  NOT EXISTS (SELECT 
	1
	FROM RoleUsers
	WHERE (ID = RoleUsers.UserID) AND ((RoleUsers.RoleID = 1) OR (CASE WHEN (RoleUsers.RoleID <> 1) THEN cast(1 as bit) WHEN (RoleUsers.RoleID = 1) THEN cast(0 as bit) END IS NULL))
)

按照我的理解,其中:

CASE WHEN (RoleUsers.RoleID <> 1) THEN cast(1 as bit) WHEN (RoleUsers.RoleID = 1) THEN cast(0 as bit) END IS NULL

類似於下面的判斷:

RoleUsers.RoleID  IS NULL

只是不知道為啥會生成這麼令人費解的程式碼。因為如果 RoleUsers.RoleID為NULL的話,既不會走進第一個WHEN,也不會走進第二個WHEN,自然就是NULL IS NULL為true了。

下面簡單寫個SELECT來驗證我的想法:

select CASE WHEN (null <> 1) 
					THEN cast(1 as bit) 
					WHEN (null = 1) 
					THEN cast(0 as bit) 
			END 
	

  

注意,這個NULL<>1的結果是FALSE,NULL=1的結果也是FALSE,所以最終的結果才是NULL。

再來看一個簡單的SELECT查詢:

下載或捐贈AppBox

2. AppBox v3.0 是捐贈軟體,你可以通過捐贈作者來獲取AppBox v3.0的全部原始碼(http://fineui.com/donate/)。

日寇忘我之心不死,同志尚需警惕!紀念九一八。

相關推薦

AnyAll用法Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 屬於某個角色的使用者列表(Any的用法) 使用Subsonic,我們有兩種方法獲取屬於某個角色的使用者列表,分別是表關聯和子查詢。 Subsonic的表關聯實現:

關聯表查詢更新Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 關聯表的查詢操作 使用 Include 方法,我們可以在一次資料庫查詢中將關聯表的資料一併取出。 比如查詢線上使用者列表頁面,需要在前端顯示關聯的使用者資訊,如下所

NHibernateEFEntity Framework的區別

概述長久以來,程式設計師和資料庫總是保持著一種微妙的關係,在商用應用程式中,資料庫一定是不可或缺的元件,這讓程式設計師一定要為了連線與訪問資料庫而去學習 SQL 指令,至少對於我而言,我覺得這是一個很不爽的事情。因此在資訊業中有很多人都在研究如何將程式設計模型和資料庫整合在一

【轉】在使用實體框架Entity Framework的應用中加入審計信息Audit trail跟蹤數據的變動

要求 date ted hang ng- tar () eat code 在一些比較重要的業務系統中,通常會要求系統跟蹤數據記錄的變動情況。系統要記錄什麽時間,什麽人,對那些信息進行了變動。 比較簡單的實現方式是在每個表中加入兩個字段CreatedBy和CreatedA

C#:實體框架EFentity framework

本文來自:http://www.cnblogs.com/xuf22/articles/5513283.html 一、什麼是Entity Framework     微軟官方提供的ORM工具,ORM讓開發人員節省資料庫訪問的程式碼時間,將更多的時間放到業務邏輯層程式碼上。EF提供變更跟蹤

Attach陷阱Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 Attach方法 前面我們已經多次使用Attach方法,上一次使用Attach方法修改使用者所屬部門的程式碼如下所示: if (String.IsNullOrEmp

如何向OrderBy傳遞字串引數Entity Framework

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 Entity Framework提供的排序功能  再來回顧一下上篇文章,載入使用者列表並進行排序資料庫分頁的程式碼: var q = DB.Users.Incl

ASP.NET網站開發--實體框架EFEntity Framework

1、什麼是Entity Framework! 它就是微軟提供的ORM工具,ORM讓開發人員節省訪問資料庫的時間,將更多的時間放在業務邏輯程式碼層中,EF提供變更追蹤,唯一性約束,惰性載入,查詢事物等!開發人員使用Linq語言對資料庫操作如同操作Object一樣省事。 2、

C#綜合揭祕——利用泛型反射更新實體ADO.NET Entity Framework

自從ADO.NET Entity Framework面世以來,受到大家的熱捧,它封裝了大量程式碼生成的工具,使用者只需要建立好實體之間的關係,系統就是會為使用者自動成功了Add、Delete、CreateObject、Attach、ToList......等等方法,這些方法

django之ORM介紹基本用法

  一、ORM介紹 1.什麼是ORM ORM 全拼Object-Relation Mapping. 中文意為 物件-關係對映. 在MVC/MVT設計模式中的Model模組中都包括ORM 2.ORM優勢 (1)只需要面

python中內建函式any()all()的用法

python中內建函式all()和any()的區別 原文:https://blog.csdn.net/quanqxj/article/details/78531856 all(x) 是針對x物件的元素而言,如果all(x)引數x物件的所有元素不為0、”、False或者x為空物件,則返回True,

網站分頁功能的實現Entity Framework和ADO.NET兩種綜述

專案中用到了分頁,上次是用的是Entity Framework,這次用ADO.NET,都是老師講的,有必要總結一下,加深下記憶。 一、Entity Framework中完成分頁 老師就講了一種,在從資料庫倒序查詢到想要的list後,在對應的使用者控制元件的.cs檔案中用了兩

CalendarView功能用法日曆檢視

簡單介紹一下CalendarView功能與用法 佈局程式碼 <LinearLayout xmlns:android="http://schemas.android.com/apk/

Hibernate中實體型別Entity Type值型別Value Type的概念分析

Hibernate中的實體型別和值型別,大家在實際應用中都有一個大致的概念,但是如何更明確的給他們下一個合適的定義呢? 我們需要從Hibernate看待各種物件出發。 物件內有用於標識用的屬性(一般都

Entity Framework Core入門二、EFCore數據庫配置生成

model res ise runtime 準備 cookie bili request data 延續上一章節https://www.cnblogs.com/dzw159/p/10646368.html 我們準備將按照AspCore的依賴註入機制獲取appsetting

團隊作業5——測試發布Alpha版本

發布說明 實現 http 基礎 相差 還需 導致 延遲 要求 Alpha版本測試報告 一、測試找出的bug (1)練習模式的測試 在測試中發現的bug如下: ① 連續兩個運算數當做一個處理(如1和2連續輸入當做12處理) ② 練習模式沒有提示答案 ③

集美大學網絡1413第九次作業成績團隊五 -- 測試發布Alpha版本

ima worker str ges 運行 .cn png www text NO.NE團隊的項目鏈接有效,六個核桃和六指神功團隊可以請教下他們,避免因IP地址無效或者因tomcat不打開就不能訪問的情況,畢竟助教沒辦法知道此時此刻它是開著還是關閉啊啊啊。。。 題目 團隊作

vector最最最基礎用法非原創

sort排序 兩個 src per pre 開始 程序 -1 logs 在c++中,vector是一個十分有用的容器,下面對這個容器做一下總結。 1 基本操作 (1)頭文件#include<vector>. (2)創建vector對象,vector<int

團隊作業9——測試發布Beta版本

登錄 iter 學生 情況 需要 上班族 監測 方法 alt Beta版本發布說明 1.在測試過程中總共發現了多少Bug?每個類別的Bug分別為多少個? a. 修復的bug:收藏功能添加出錯。 b. 不能重現的bug:暫未發現。 c. 這個產品就是這樣設計的,不是bug:暫

Linux系統Oracle 12cR2 RAC集群安裝維護管理12.2專題

oracle教程 oracle培訓 oracle數據庫教程 oracle工程師培訓 oracle數據庫培訓 風哥Linux系統Oracle 12cR2 RAC集群安裝與維護管理(12.2)專題包括內容:Oracle數據庫12cR2(項目實戰之一):在Windows上安裝Oracle12.2