/// <summary>
/// EF針對 留言數據庫 的 數據上下文對象!!!!
/// </summary>
static LeaveWordBoradEntities db = new LeaveWordBoradEntities();
static Program()
{
//關閉 實體屬性 的 驗證檢查
db.Configuration.ValidateOnSaveEnabled = false;
}
#region 1.0 新增 -void Add()
/// <summary>
/// 1.0 新增
/// </summary>
static void Add()
{
//1.1創建實體對象
User uObj = new User()
{
uName = "劉德華",
uLoginName = "aaa",
uPwd = "asdfasdfasdfsadf",
uIsDel = false,
uAddtime = DateTime.Now
};
//1.2通過EF新增到數據庫
//1.2.1將對象 加入到 數據上下文 的 User集合中
//db.Users.Add(uObj);
DbEntityEntry<User> entry = db.Entry<User>(uObj);
entry.State = System.Data.EntityState.Added;
//1.2.2調用數據上下文 的 保存方法,將 對象 存數數據庫
db.SaveChanges();
Console.WriteLine("保存成功~~!");
}
#endregion
#region 2.0 簡單查詢 -void Query()
/// <summary>
/// 2.0 簡單查詢
/// </summary>
static void Query()
{
//2.0 IEnumerable(集合) 和 IQueryable(EF里的DbSet<T>) 里的 SQO 本質不一樣!:
//2.1 集合 的 標准查詢運算符 方法 ,是來自於 System.Linq.Enumerable 里 給 IEnumerable 接口添加的擴展方法
//List<string> listStr = new List<string>();
//listStr.Where
//EF上下文里的 DBSet<T> 里的 標准查詢運算符 方法,來自於 System.Linq.Queryable 里給 IQueryable接口 添加的擴展方法
//2.2 變相的 即時查詢
List<User> list = db.Users.Where(u => u.uName == "劉德華").ToList();
list.ForEach(u => Console.WriteLine(u.ToString()));
}
#endregion
#region 2.1 簡單查詢 延遲加載 -void QueryDelay_01()
//【延時加載】 看成兩種:
//2.1 EF本身查詢方法 返回的都是 IQueryable接口,此時並未查詢數據庫;只有當調用接口方法 獲取 數據時,才會查詢數據庫
//2.1.1 【延時加載】,本質原因之一:當前可能通過多個SQO方法 來組合 查詢條件,那么每個方法 都只是添加一個查詢條件而已,無法確定本次查詢條件 是否 已經添加結束
// 所以,沒有辦法在每個SQO方法的時候確定SQL語句是什么,只能返回一個 包含了所有添加的條件的 DBQuery 對象,
// 當使用這個 DBQuery對象 的時候,才根據所有條件 生成 sql語句,查詢數據庫
static void QueryDelay_01()
{
DbQuery<User> dbQuery = db.Users.Where(u => u.uLoginName == "劉德華").OrderBy(u => u.uName).Take(2) as System.Data.Entity.Infrastructure.DbQuery<User>;
//獲得 延遲查詢對象后,調用對象的 獲取第一個數據方法,此時,【就會根據之前的條件】,生成sql語句,查詢數據庫了~~!
User usr01 = dbQuery.FirstOrDefault();// ToList()......
Console.WriteLine(usr01.uLoginName);
}
//2.1.2【延遲加載】- 針對於 外鍵實體 的延遲(按需加載)!
// 本質原因之二:對於外鍵屬性而言,EF會在用到這個外鍵屬性的時候才去查詢 對應的 表。
static void QueryDelay_02()
{
IQueryable<UsersAddress> addrs = db.UsersAddresses.Where(a => a.udUId == 1);//真實返回的 DbQuery 對象,以接口方式返回
//a.此時只查詢了 地址表
UsersAddress addr01 = addrs.FirstOrDefault();
//b.當訪問 地址對象 里的 外鍵實體時,EF會查詢 地址對應 的用戶表;查詢到之后,將數據 裝入 這個外鍵實體
Console.WriteLine(addr01.User.uName);
//c.【延遲加載】按需加載 的缺點:每次調用外鍵實體時,都會去查詢數據庫(EF有小優化:相同的外鍵實體只查一次)
IQueryable<UsersAddress> addrs2 = db.UsersAddresses;
foreach (UsersAddress add in addrs2)
{
Console.WriteLine(add.udAddress + ":userName=" + add.User.uName);
}
}
#endregion
#region 2.2 連接查詢(生成 inner join) -void QueryInnerJoin()
/// <summary>
/// 2.2 連接查詢(生成 inner join)
/// </summary>
static void QueryInnerJoin()
{
//通過Include方法,設置 EF 生成 sql 語句時,使用 inner join 把 地址表對應的 User屬性 也查出來
// select * from UsersAddresses a inner join Users u on a.udId =u.id
IQueryable<UsersAddress> addrs = db.UsersAddresses.Include("User").Where(a => a.udId == 1);
foreach (UsersAddress add in addrs)
{
Console.WriteLine(add.udAddress + ":userName=" + add.User.uName);
}
//練習:查詢消息表的同時,顯示 消息發送人 和 接收名字
IQueryable<Msg> msgs = db.Msgs.Include("User").Include("User1");
foreach (Msg m in msgs)
{
Console.WriteLine(m.mId + ",發送人:" + m.User.uName + ",接收人:" + m.User1.uName + ",消息內容:" + m.mMsg);
}
}
#endregion
#region 3.0 官方推薦的 修改方式(先查詢,再修改)
/// <summary>
/// 3.0 官方推薦的 修改方式(先查詢,再修改)
/// </summary>
static void Edit()
{
//1.查詢出一個 要修改的對象 -- 注意:此時返回的 是 一個 User類的 代理類對象(包裝類對象)
User usr = db.Users.Where(u => u.uId == 1).FirstOrDefault();
Console.WriteLine("修改前:" + usr.ToString());
//2.修改內容 -- 注意:此時其實操作的 是 代理類對象 的屬性,這些屬性,會將 值 設置給 內部的 User對象對應的屬性,同時 標記此屬性為已修改狀態
usr.uName = "劉德華";
usr.uLoginName = "liudehua";
//3.重新保存到數據庫 -- 注意:此時 ef上下文,會檢查容器內部 所有的對象,找到 標記為修改的 對象,然后 找到 標記為修改的 對象屬性,生成對應的 update語句 執行!
db.SaveChanges();
Console.WriteLine("修改成功:");
Console.WriteLine(usr.ToString());
}
#endregion
#region 3.1 自己優化的 修改方式(創建對象,直接修改)
/// <summary>
/// 3.1 自己優化的 修改方式(創建對象,直接修改)
/// </summary>
static void Edit2()
{
//1.查詢出一個 要修改的對象
User usr = new User() { uId = 8,uName="小白~~~"};
//2.將 對象 加入 EF容器,並獲取 當前實體對象 的 狀態管理對象
DbEntityEntry<User> entry = db.Entry<User>(usr);
//3.設置 該對象 為被修改過
entry.State = System.Data.EntityState.Unchanged;
//4.設置 該對象 的 uName屬性 為 修改狀態,同時 entry.State 被修改為 Modified 狀態
entry.Property("uName").IsModified = true;
//var u = db.Users.Attach(usr);
//u.uName = "小白~~";
//3.重新保存到數據庫 -- ef 上下文 會 根據 實體對象的 狀態 ,根據 entry.State =Modified 的值 生成 對應的 update sql 語句
db.SaveChanges();
Console.WriteLine("修改成功:");
Console.WriteLine(usr.ToString());
}
#endregion
#region 4.0 刪除 -void Delete()
/// <summary>
/// 4.0 刪除
/// </summary>
static void Delete()
{
//4.1創建要刪除的 對象
User u = new User() { uId = 10 };
//4.2附加到 EF中
db.Users.Attach(u);
//4.3標記為刪除 注意:此方法 就是 起到了 標記 當前對象 為 刪除狀態 !
db.Users.Remove(u);
/*
也可以使用 Entry 來附加和 修改
DbEntityEntry<User> entry = db.Entry<User>(u);
entry.State = System.Data.EntityState.Deleted;
*/
//4.4執行刪除sql
db.SaveChanges();
Console.WriteLine("刪除成功~~~");
}
#endregion
#region 5.0 批處理 -- 上下文 SaveChanges 方法 的 好處!!!!
/// <summary>
/// 批處理 -- 上下文 SaveChanges 方法 的 好處!!!!
/// </summary>
static void SaveBatched()
{
//5.1新增數據
User uObj = new User()
{
uName = "劉德華",
uLoginName = "aaa",
uPwd = "asdfasdfasdfsadf",
uIsDel = false,
uAddtime = DateTime.Now
};
db.Users.Add(uObj);
//5.2新增第二個數據
User uObj2 = new User()
{
uName = "劉德華2",
uLoginName = "aaa2",
uPwd = "asdfasdfasdfsadf2",
uIsDel = false,
uAddtime = DateTime.Now
};
db.Users.Add(uObj2);
//5.3修改數據
User usr = new User() { uId = 8, uName = "又黑了~~~" };
DbEntityEntry<User> entry = db.Entry<User>(usr);
entry.State = System.Data.EntityState.Unchanged;
entry.Property("uName").IsModified = true;
//5.4刪除數據
User u = new User() { uId = 11 };
//4.2附加到 EF中
db.Users.Attach(u);
//4.3標記為刪除 注意:此方法 就是 起到了 標記 當前對象 為 刪除狀態 !
db.Users.Remove(u);
db.SaveChanges();
Console.WriteLine("批處理 完成~~~~~~~~~~~~!");
}
#endregion
#region 5.1 批處理 -- 一次新增 50條數據 -void BatcheAdd()
/// <summary>
/// 5.1 批處理 -- 一次新增 50條數據
/// </summary>
static void BatcheAdd()
{
for (int i = 0; i < 50; i++)
{
User uObj = new User()
{
uName = "劉德華" + i,
uLoginName = "aaa" + i,
uPwd = "asdfasdfasdfsadf" + i,
uIsDel = false,
uAddtime = DateTime.Now
};
db.Users.Add(uObj);
}
db.SaveChanges();
}
#endregion