EF操作與Linq寫法記錄、First、FirstOrDefault、Single、SingleOrDefault幾個方法的區別
1、EF引入
新建一個MVC專案之後,要引用EF框架,可以按照以下步驟進行:
1),在Models中新增專案
2),選擇Entity DataModel,並重新填寫名字
3),選擇程式碼優先之後,選擇連線的資料庫以及表,之後便生成,此時模型裡面的實體就相當於資料庫中的表了
2、Linq與一些lambda寫法
1)、單表查詢:
using (var db = new DBModel()) { DepartmentList = (from n in db.output_Auth where n.badge == badge select n.department).Distinct().ToList<string>(); } //from n(表別名) in table(表格) where n.id == id(條件) select n(查詢該表所有),然後後面可以選擇篩選的條件,比如.Distinct()\FirstOrDefault()\Sum()等
//select 中想要查詢具體的某個欄位,寫法為:select new {n.id, n.name, n.age}等,欄位想賦予別名,寫法為:select new {anotherID = n.id, anotherName = n.name}
注:幾個本專案中常用的方法:
1、OrderByDescending(n => n.id); //降序排列
2、FirstOrDefault(); //獲取查詢結果的第一行
3、ToList(); //將查詢結果列表化
4、Distinct(); //將查詢結果單一化,類似於SQL中的 distinct
5、Sum(n => n.id); //結果總和
剩下的在此次專案中未用到,將來使用到再總結。
2)、多表查詢:
var time1 = (from a in Table_A join b in Table_B on a.id equals b.id where a.id == id & b.time == timeselect new { a.time, a.data}).ToList();
//在這裡和SQL的多表查詢語句寫法不太同,on後面的條件寫法為: a.x equals b.x
//補充1:無法直接在 Linq to SQL 的語句中將時間格式化,只能先查詢出來了,再在 Linq to Entity 中格式化時間
即上面查詢語句 where b.time == time 中,b.time 不能寫成 b.time.ToString("yyyy-MM-dd") 之類的
只能將查到的時間放在 time1 中,再對時間進行格式化,如下:
var time2 = (from t in time1 where t.time.GetDataTimeFormats()[5].ToString() == nowDate select new{Data = t.data}).Sum(t => t.Data);
GetDateTimeFormats()[5]時間格式:yyyy-MM-dd
//補充2:LinQ to SQL 中查詢的結果如果為0,則無法直接使用.Sum()求和,應該先將查詢的結果.ToList(),再進行第二步,在 LinQ to Entity 中進行求和。類似於上面的寫法,需要寫兩條語句。
3)、插入與更新語句
using (var db = new DBModel()) {
//插入之前先查詢有沒有該資料 var data = (from tb in db.Table where tb.id == id select tb).FirstOrDefault();
//如果沒有該資料,則執行插入語句 if (data == null) { var table = new Table();
table.name = name;
table.age = age;
//執行插入操作 db.Table.Add(table);
db.SaveChanges();
}
//如果當月有資料 else { //Linq無法直接更新主鍵的資料,只能是先將此條資訊複製出來,把原來的那條資料刪除,再重新插入一條修改後的資料,若不是主鍵資料,則直接更新 var tableNew = new Table(); tableNew.name = name; tableNew.age = age; db.Table.Remove(data); //移除老資料 db.Table.Add(tableNew); //新增新資料 //執行更新操作 db.SaveChanges(); } }
//Lambda 表示式新增寫法 :
vardata = db.Table.FirstOrDefault(tb => tb.id == id & tb.name == name);
if (data ==null)
{
vartable =newTable();
table.name = name;
table.age = age;
db.Table.Add(table);
db.SaveChanges();
}
//Lambda 修改:
vartable = db.Table.FirstOrDefault(tb => tb.id == id);
table.name = name;
table.age = age;
db.SaveChanges();
4)、刪除
//Lambda表示式寫法: using (var db = new DBModel()) { var user = db.Table.FirstOrDefault(opAu => opAu.ID == userID); db.Table.Remove(user); db.SaveChanges(); } //Linq寫法: using (var db = new DBModel()) { var user = (from tb in db.Table select tb).FirstOrDefault(); db.Table.Remove(tb); db.SaveChanges(); }
EF中使用Linq時First、FirstOrDefault、Single、SingleOrDefault幾個方法的區別
在使用EntityFramework開發時,.NET的System.Linq.Enumerable類為我們提供了許多Linq方法。
給大家分享一下關於First、FirstOrDefault、Single、SingleOrDefault幾個方法的區別例項及使用場景,首先是關於這幾個方法的定義:
●First:返回序列中的第一條記錄,如果沒有記錄,則引發異常。
●FirstOrDefault:返回序列中的第一條記錄,如果沒有記錄,則返回預設值。
●Single:返回序列中的唯一記錄,如果沒有或返回多條記錄,則引發異常。
●SingleOrDefault:返回序列中的唯一記錄;如果該序列為空,則返回預設值;如果該序列包含多個元素,則引發異常。
二、例項和用法
1、First與FirstOrDefault
◆ First返回序列中的第一條記錄,如果沒有記錄,則引發異常,示例程式碼如下:
static void Main(string[] args) { string[] strName = { "Fred", "Gary", "William", "Charles" }; string[] strNameEmpty = { }; try { string tempName = strName.First(); Console.WriteLine("First()第一種 返回序列中的第一條記錄。"); Console.WriteLine("資訊為:{0}", tempName); //如果序列中沒有元素則會發生,InvalidOperationException 異常。 源序列為空。 string tempNameEmpty = strNameEmpty.First(); } catch (Exception ex) { Console.WriteLine("First()第二種 返回序列中沒有元素,引發異常。"); Console.WriteLine("資訊為:{0}", ex.Message); } }
結果如下圖所示:
◆ FirstOrDefault返回序列中的第一條記錄,如果序列中不包含任何記錄,則返回預設值(對於可以為null的物件,預設值為null,對於不能為null的物件,如int,預設值為0),示例程式碼如下:
static void Main(string[] args) { string[] strName = { "Fred", "Fred", "William", "Charles" }; string[] strNameEmpty = { };// string 型別的預設值是空 string tempName = strName.FirstOrDefault(); Console.WriteLine("FirstOrDefault()第一種 返回序列中的第一條記錄。"); Console.WriteLine("資訊為:{0}", tempName); string tempNameEmpty = strNameEmpty.FirstOrDefault(); Console.WriteLine("FirstOrDefault()第二種 如果序列中不包含任何記錄,則返回預設值。"); Console.WriteLine("資訊為:{0}", tempNameEmpty); }
結果如下圖所示:
2、Single與SingleOrDefault
◆Single返回序列中的唯一一條記錄,如果沒有或返回多條,則引發異常,示例程式碼如下:
static void Main(string[] args) { string[] strName = { "Fred"}; string[] strNameEmpty = { }; try { string tempName = strName.Single(); Console.WriteLine("Single()第一種 返回序列中的唯一一條記錄。"); Console.WriteLine("資訊為:{0}", tempName); //沒有或返回多條,則引發異常。 string[] strNameEmpty = { "Fred","Crazy"}; string tempNameEmpty = strNameEmpty.Single(); } catch (Exception ex) { Console.WriteLine("Single()第二種 沒有或返回多條,則引發異常。"); Console.WriteLine("資訊為:{0}", ex.Message); } }
結果如下圖所示:
◆SingleOrDefault返回序列中滿足指定條件的唯一元素;如果這類元素不存在,則返回預設值;如果有多個元素滿足該條件,此方法將引發異常,示例程式碼如下:
static void Main(string[] args) { string[] strName = { "Fred"}; string[] strNameEmpty = { }; string[] strEmpty = { "Fred", "Crazy" }; try { string tempName = strName.SingleOrDefault(); Console.WriteLine("SingleOrDefault()第一種 返回序列中的唯一記錄。"); Console.WriteLine("資訊為:{0}", tempName); string tempNameEmpty = strNameEmpty.SingleOrDefault(); Console.WriteLine("SingleOrDefault()第二種 如果該序列為空,則返回預設值。"); Console.WriteLine("資訊為:{0}", tempNameEmpty); //序列包含多個元素,則引發異常 string[] strNameEmpty = { "Fred","Crazy"}; string tempEmpty = strEmpty.SingleOrDefault(); } catch (Exception ex) { Console.WriteLine("SingleOrDefault()第三種 如果該序列包含多個元素,則引發異常。"); Console.WriteLine("資訊為:{0}", ex.Message); } }
結果如下圖所示:
三、什麼時候用First、FristOrDefault、Single、SingleOrDefault?
1、當集合中只有一個元素時,可以使用Single。
2、當集合中不包含任何元素但需要返回預設值時,可以使用SingleOrDefault。
3、當集合中包含多個元素並想丟擲異常時,可以使用Single或SingleOrDefault。
4、無論集合中是否有元素,我們都想要返回一個記錄時,可以使用First或FirstOrDefault。
5、當集合中不包含任何元素但需要返回預設值時,可以使用FirstOrDefault。
四、總結
First和Single的區別:前者是TOP(1)後者是TOP(2),後者如果查詢到兩條資料則丟擲異常。所以在必要的時候使用Single也不會比First慢多少。
FirstOrDefault與SingleOrDefault的效能比較:
FirstOrDefault通常在效能上會比SingleOrDefault表現得比優,因為FirstOrDefault是從集合開始位置查詢到第一個匹配的元素就返回,而SingleOrDefault會迭代集合中所有的元素。
助記:有OrDefault的方法會返回值(如果沒有符合條件的元素,則返回預設值),沒有OrDefault的方法會丟擲異常。
方法名 |
|
|
|
First() |
一條記錄 |
返回沒有,則異常 |
|
FirstOrDefault() |
一條記錄 |
返回沒有,預設值 |
|
Single() |
一個記錄 |
返回沒有,則異常 |
多條異常 |
SingleOrDefault() |
一個記錄 |
返回沒有,預設值 |
多條異常 |