創建上下文對象:TestDBEntities db = new TestDBEntities();
一、增:
//1.1創建實體對象方式一
User uObj = new User() { uName = "劉德華", uLoginName = "aaa", uPwd = "asdfasdfasdfsadf", uIsDel = false, uAddtime = DateTime.Now };
//創建實體方式二
//User user = new User(); //user.LoginName = "ssss"; //user.Mail = "ssss"; //user.PassWord = "ssss"; //user.Plane = "ssss"; //user.UserName = "ssss"; //user.phone = "ssss";
//1.2.1告訴EF咱們對上面的實體做一個插入操作
db.Users.Add(uObj);
//1.2.2告訴上下文把實體的變化保存到數據庫里面去
db.SaveChanges();
//1.3 添加用戶時可以關聯導航屬性:
UserInfo與OrderInfo存在一對多關系 //創建一個用戶 //UserInfo userInfo = new UserInfo(); //userInfo.UName = "yang"; //告訴上下文我們對這個實體做添加操作 //dbContext.UserInfo.Add(userInfo); //創建兩個訂單 //OrderInfo order1 = new OrderInfo(); //order1.Content = "shit1"; //dbContext.OrderInfo.Add(order1); //OrderInfo order2 = new OrderInfo(); //order2.Content = "shit2"; //dbContext.OrderInfo.Add(order2); //關聯三個實體 //1、通過用戶添加訂單實體到自己的導航屬性 //userInfo.OrderInfo.Add(order1); //2、通過訂單指定用戶實體 //order2.UserInfo = userInfo; ////order2.UserInfoID = userInfo.ID;
二、刪除:
EF中實現刪除有三種方式,版本一、二都是根據主鍵刪除,版本三是根據任意條件到數據庫查詢然后再根據查詢的結果進行刪除,實際上版本三也是根據查詢出來的結果中的主鍵進行刪除。
1 :根據主鍵刪除方式一
//實例化一個Users對象,並指定Id的值 Users user = new Users() { Id = 1 }; //將user附加到上下文對象中,並獲得EF容器的管理對象 var entry = db.Entry<User>(user);或者 var entry=db.Entry(user); //設置該對象的狀態為刪除 entry.State = EntityState.Deleted; //以上兩步可並作一步 //dbContext.Entry<USER>(user).State = System.Data.EntityState.Modified; //保存修改 db.SaveChanges();
2:根據主鍵刪除方式二
//實例化一個Users對象,並指定Id的值 Users user = new Users() { Id = 1 }; //將user附加到上下文對象中 db.Users.Attach(user); //注意:附加的實體對象事先不能已經在上下文中,否則上下文會追蹤到兩個相同鍵名的實體對象而報錯。 //刪除user對象 Db.Users.Remove(user); //保存修改 db.SaveChanges();
3:先根據條件查詢出來然后再刪除
//3.1 一下只刪除一個
// linq方式 var user = (from v in db.Users where v.ID == 14 select v).Single(); //拉姆達方式 //var user= db.Users.Where(u => u.ID==2).firstOrDefault(); db.UserInfo.Remove(user); db.SaveChanges(); //3.2一下刪除一個或多個 var list= db.Users.Where(u => u.Name ==”張三”); if (list != null && list.Any()) // Any作用:如果源序列包含任何元素,則為 true;否則為 false。 { foreach (var item in list) { db.Users.Remove(item); } } db.SaveChanges();
三、修改:
//方式一:先將Id為2的Users數據查詢出來,在修改。(這是代碼最少的方式)
var user = db.Users.Where(u => u.Id == 2).FirstOrDefault(); //修改UserName屬性 user.UserName = "222222222222222"; //保存修改 db.SaveChanges(); //由於查詢出來的實體對象本身就在上下文中,所以不需要再附加到上下文。
//方式二:聲明一個User實體
USER user = new USES(); user.LoginName = "ssss111--------"; user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss"; user.UserName = "ssss"; user.cardNo = "ssss"; user.phone = "ssss"; user.ID = 8;//修改刪除的時候必須指定id(主鍵)
//3、告訴上下文咱們的對此實體進行更新操作。
//db.Entry<USER>(user).State = System.Data.EntityState.Modified;
//4、告訴上下文把實體的變化保存到數據庫里面去。
db.SaveChanges();//真正執行sql腳本的地方。
// 方式三 只修改部分字段
USER user = new USES(); user.LoginName = "ssss111--------"; user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss"; user.UserName = "ssss"; user.cardNo = "ssss"; user.phone = "ssss"; db.USER.Attach(user);//附加到上下文里面來管理 //指定要修改的字段(強類型方式) db.Entry<USER>(user).Property<string>(u => u.LoginName).IsModified = true; //指定要修改的字段(弱類型方式),推薦使用強類型因為有強類型校驗。 //db.Entry<USER>(user).Property("LoginName").IsModified = true; db.SaveChanges(); //注意:上面的泛型<USER>、<string>可以省略,因為可以編譯階段會根據實體自動推斷,如下 //db.Entry (user).State = System.Data.EntityState.Modified; //db.Entry (user).Property (u => u.LoginName).IsModified = true;
方式四 空值字段處理,關閉實體合法性檢查
//1)創建出一個要修改的對象 User use = new User() { uId = 8,uName="小白~~~"}; //2)將對象加入 EF容器,並獲取當前實體對象的狀態管理對象 DbEntityEntry<User> entry = db.Entry<User>(user); //3)設置該對象為未被修改過 entry.State = System.Data.EntityState.Unchanged; //4)設置該對象的 uName屬性為修改狀態,同時 entry.State 被修改為 Modified 狀態 entry.Property("uName").IsModified = true; //5)關閉EF實體合法性檢查(如果創建出來的要修改的數據有的字段沒有賦值則關閉實體合法性檢查,如果所有字段都賦值了則不用關閉EF實體合法性檢查) db.Configuration.ValidateOnSaveEnabled = false; //6)重新保存到數據庫 -- ef 上下文會根據實體對象的狀態,根據 entry.State =Modified 的值生成對應的 update sql 語句. db.SaveChanges();
注意:增刪改操作都需要執行db.SaveChange(),否則不會去操作數據庫。
四、查詢:
查詢方式有兩種,一種是拉姆達表達式(一般點出來),一種是linq(類似於sql)。
(一)linq 方式舉例
IQueryable<USER> temp = from u in db.USER where u.ID > 4 select u;
(二)拉姆達表達式:
1、單行
var userLogin = db.T_UserLogin.Where(d => d.LoginID == loginID).FirstOrDefault();
2、多行()
1)var list = db.Users.Where(u => u.uName == "劉德華").ToList(); 2)List<User> list = db.Users.Where(u => u.uName == "劉德華").ToList();
3、連接查詢:
1)linq連接查詢: from a in db.User join b in db. UsersAddresses on a.Id equals b.udid 2)拉姆達表達式連接查詢:IQueryable<UsersAddress> addrs = db.User.Include("UsersAddresses").Where(a => a.Id == 1); 3)另一種連接查詢:var list=db.User.Join(db. UsersAddresses,c=>c.Id,g=>g.udid,(c,g)=>new{Name=c.Name,GroupName=g.GroupName});
查詢還遠遠不只這點,有需要請百度linq查詢系統學習。
五、增刪改查的另一種方式,純sql。
當遇到復雜的需求,需要書寫復雜語句,但有不特別熟悉EF語法時有兩種方案:
1.數據庫中創建視圖或存儲過程
2純sql方式;
//1)查詢SqlQuery
簡單用法
result.slList = db.Database.SqlQuery<DataTemp>("select Precision,Year,LandCover, sum(Area) as Area from [EcoTypes] where LandCover=@type group by Precision, Year, LandCover", new SqlParameter("@type", "森林")).Select(d=> d.Area).ToList();
復雜用法
//var sql = "select cc.GermID, cc.Name,cc.EnglishName, c.SamplingMethod,c.BatchID," + // "Max(case c3.LocationID when 1 then c.DataValue*100 else 0 end) as '交通樞紐'," + // "Max(case c3.LocationID when 2 then c.DataValue*100 else 0 end) as '居民區'," + // "Max(case c3.LocationID when 3 then c.DataValue*100 else 0 end) as '文教區'," + // "Max(case c3.LocationID when 4 then c.DataValue*100 else 0 end) as '城市綠地'," + // "Max(case c3.LocationID when 5 then c.DataValue*100 else 0 end) as '中心商務區'," + // "Max(case c3.LocationID when 6 then c.DataValue*100 else 0 end) as '商業區'," + // "Max(case c3.LocationID when 7 then c.DataValue*100 else 0 end) as '旅游區'," + // "Max(case c3.LocationID when 8 then c.DataValue*100 else 0 end) as '工業區'" + // " from [dbo].T_GermData as c " + // " inner join [dbo].T_Germ as cc on c.GermID=cc.GermID " + // " inner join [dbo].[T_MicrobeLocations] as c3 on c3.LocationID=c.LocationID " + // " where c.BatchID=1 and c.SamplingMethod=@SamplingMethod" + // " group by cc.GermID, cc.Name, cc.EnglishName,c.SamplingMethod,c.BatchID"; //var sqlParams = new SqlParameter[] //{ // new SqlParameter("@SamplingMethod",System.Data.SqlDbType.SmallInt) {Value= samplingMethod}, //}; //var data = db.Database.SqlQuery<GermTemp>(sql, sqlParams);
如果需要更靈活或復雜,可以考慮在數據庫寫存儲過程。
//2)增刪改:ExecuteSqlCommand
db.Database.ExecuteSqlCommand("").ToString();
詳情請百度 db.Database. 此時會出現使用方式和相應的說明文字。
六、linq學習資料整理
LINQ的全稱是Language Integrated Query,中文譯成“語言集成查詢”,主要用於查詢。舉一個簡單的例子,比如說sql語句:select userName from t_user where userID = 1;這句sql語句可以分為哪幾部分,他們各自的執行順序是什么。當然有select,from,where三層,執行的順序當然是先from ,再where,在select,所以將上述sql轉成linq為:
var query= from user in DBcontext.t_user where user.userID == 1 select user;
3)linq學習資料整理:
https://www.cnblogs.com/hao-1234-1234/p/11175410.html
七、相關概念
1)數據持久化
是將內存中的數據模型轉換為存儲模型,以及將存儲模型轉換為內存中的數據模型的統稱;數據模型可以是任何數據結構或對象模型,存儲模型可以是關系模型、XML、二進制流等;其實,簡單來說,就是將數據存儲到數據庫中,為什么這么說呢?因為持久化就不是暫時的,而存儲分為暫存和永存兩個方面,暫存指的是存儲到了計算機的內存中,電源關閉即丟失。而永存就是存儲到了類似數據庫里,數據就可以反復使用。除此以外,持久化封裝了數據訪問細節,為大多數業務邏輯提供面向對象的API。
1. 通過持久化技術可以減少訪問數據庫數據次數,增加應用程序執行速度;
2. 代碼重用性高,能夠完成大部分數據庫操作;
3. 松散耦合,使持久化不依賴於底層數據庫和上層業務邏輯實現,更換數據庫時只需修改配置文件而不用修改代碼。
八、問題與思考
1 、建議從客戶端(前端)、代碼服務器(后台)、數據庫服務器 三個方向思考問題,代碼服務器覺得困難問題前端和數據庫端都很簡單。
2 、換一種技術路線,對EF困難的問題,對原生ADO代碼可能不難。(注意,除非遇到無法解決的問題,一般不建議同時多種技術路線,減少學習難度,方便日后維護。)
3、速度,當你遇到對速度的極高要求時,EF這種ORM框架,甚至大多數orm框架都不在實用,這時要返璞歸真,最求極致的簡單。但又要可控:開發進度可控,安全可控,后期可維護可能等。
4、性能瓶頸和綜合成本
1)綜合考慮硬件:帶寬、IO、內存、安全等,
帶寬:傳遞給前端數據盡可能少、前端代碼壓縮后在發布等,可以減少對帶寬的壓力。
安全:物理隔離、代碼邏輯權限機制、前端代碼壓縮、漏洞軟件(appscan)、第三方圖片服務器及其授權機制 等
內存: 代碼服務器 計算量較大時,可以分配一些計算量到客戶端或數據庫服務器(存儲過程)。
2)綜合考慮軟件:技術體系選擇、架構設計、框架選擇、數據庫設計、代碼實現、后期運維難度 、源代碼管理等因素。
技術體系: java、.net ,這里考慮到成本和規模選擇.net
開發工具:前端vscode 、后台 vs(太卡了)
架構設計: 前后端完全分離 、mvc 等
框架選擇:后端成熟框架 webapi、前端成熟框架 vue、element、webpack、;
數據庫設計:數據庫設計工具如 Powdesigner、數據庫設計(物理位置、權限機制、分庫、分表、字段、索引、臨時表等)
代碼實現:文字規范、接口規范、功能實現
運營維護:運維設備、運維工具軟件
源代碼管理: 管理平台:國外github(網速、中英文障礙)。微軟svn、國內gitee。
這已經超過我目前的個人能力的,呵呵。
八、參考文章:
https://www.cnblogs.com/zhuyuchao/p/5634196.html
https://blog.csdn.net/weienjun/article/details/79170819
https://www.cnblogs.com/xiashengwang/archive/2012/07/28/2609161.html