AppBox 是基于 FineUI 的通用權限管理框架,包括用戶管理、職稱管理、部門管理、角色管理、角色權限管理等模塊。
Entity Framework新增數據
以新增用戶為例,作為對比,先來看下使用Subsonic的代碼:
using (TransactionScope scope = new TransactionScope()) { XUser item = new XUser(); item.Name = tbxName.Text.Trim(); item.ChineseName = tbxRealName.Text.Trim(); item.Gender = ddlGender.SelectedValue; item.CompanyEmail = tbxEmail.Text.Trim(); item.PersonalEmail = tbxPersonalEmail.Text.Trim(); item.OfficePhone = tbxOfficePhone.Text.Trim(); item.OfficePhoneExt = tbxOfficePhoneExt.Text.Trim(); item.HomePhone = tbxHomePhone.Text.Trim(); item.CellPhone = tbxCellPhone.Text.Trim(); item.Remark = tbxRemark.Text.Trim(); item.Enabled = cbxEnabled.Checked; //item.DeptId = Convert.ToInt32(ddlDept.SelectedValue); item.CreateTime = DateTime.Now; item.Save(); // 添加所有角色 if (!String.IsNullOrEmpty(hfSelectedRole.Text)) { XRoleUserCollection roleUsers = new XRoleUserCollection(); foreach (string roleIdStr in hfSelectedRole.Text.Split(',')) { int id = Convert.ToInt32(roleIdStr); XRoleUser roleUser = new XRoleUser(); roleUser.RoleId = id; roleUser.UserId = item.Id; roleUsers.Add(roleUser); } roleUsers.SaveAll(); } scope.Complete(); }
由于需要操作兩張表,所以使用了事務(TransactionScope),并在兩個數據庫操作全部完成之后調用 scope.Complete。
使用Entity Framework的代碼無需使用事務,EF會正確的處理表關聯,代碼如下:
User item = new User(); item.Name = tbxName.Text.Trim(); item.Password = PasswordUtil.CreateDbPassword(tbxPassword.Text.Trim()); item.ChineseName = tbxRealName.Text.Trim(); item.Gender = ddlGender.SelectedValue; item.CompanyEmail = tbxCompanyEmail.Text.Trim(); item.Email = tbxEmail.Text.Trim(); item.OfficePhone = tbxOfficePhone.Text.Trim(); item.OfficePhoneExt = tbxOfficePhoneExt.Text.Trim(); item.HomePhone = tbxHomePhone.Text.Trim(); item.CellPhone = tbxCellPhone.Text.Trim(); item.Remark = tbxRemark.Text.Trim(); item.Enabled = cbxEnabled.Checked; item.CreateTime = DateTime.Now; // 添加所有角色 if (!String.IsNullOrEmpty(hfSelectedRole.Text)) { int[] roleIDs = StringUtil.GetIntArrayFromString(hfSelectedRole.Text); item.Roles = DB.Roles.Where(r => roleIDs.Contains(r.ID)).ToList(); } DB.Users.Add(item); DB.SaveChanges();
上面的代碼雖說可以正常運行,但是在設置用戶角色列表時(item.Roles)進行了數據庫查詢,而這次查詢可以通過Attach方法避免,更新后的版本:
User item = new User(); item.Name = tbxName.Text.Trim(); item.Password = PasswordUtil.CreateDbPassword(tbxPassword.Text.Trim()); item.ChineseName = tbxRealName.Text.Trim(); item.Gender = ddlGender.SelectedValue; item.CompanyEmail = tbxCompanyEmail.Text.Trim(); item.Email = tbxEmail.Text.Trim(); item.OfficePhone = tbxOfficePhone.Text.Trim(); item.OfficePhoneExt = tbxOfficePhoneExt.Text.Trim(); item.HomePhone = tbxHomePhone.Text.Trim(); item.CellPhone = tbxCellPhone.Text.Trim(); item.Remark = tbxRemark.Text.Trim(); item.Enabled = cbxEnabled.Checked; item.CreateTime = DateTime.Now; // 添加所有角色 if (!String.IsNullOrEmpty(hfSelectedRole.Text)) { int[] roleIDs = StringUtil.GetIntArrayFromString(hfSelectedRole.Text); item.Roles = new List<Role>(); foreach (int roleID in roleIDs) { Role role = new Role { ID = roleID }; DB.Roles.Attach(role); item.Roles.Add(role); } } DB.Users.Add(item); DB.SaveChanges();
根據微軟官方文檔對Attach的解釋:http://msdn.microsoft.com/en-us/data/jj592676
If you have an entity that you know already exists in the database but which is not currently being tracked by the context then you can tell the context to track the entity using the Attach method on DbSet. The entity will be in the Unchanged state in the context.
Attach的數據已經存在數據庫中,但是還沒有被加載到EF上下文中 ,Attach后的實體處于Unchanged的狀態。后面我們會有詳細的博文講解Attach,到時你會發現這里對Attach的用法其實還是有點問題的。
Entity Framework刪除數據
最為對比,先來看下使用Subsonic如何刪除一組用戶:
new Delete().From<XUser>() .Where(XUser.IdColumn).In(ids) .Execute();
而使用EF的代碼并不那么直觀,因為在EF中刪除數據之間要先把數據加載到EF上下文中,如下所示:
DB.Users.Where(u => ids.Contains(u.UserID)).ToList().ForEach(u => DB.Users.Remove(u)); DB.SaveChanges();
那么有沒有辦法像Subsonic一樣刪除數據呢?其實辦法早就有了:https://github.com/loresoft/EntityFramework.Extended
我們需要在項目中添加這個庫,然后在頁面添加如下引用:
using EntityFramework.Extensions;
現在的刪除代碼就簡單多了:
DB.Users.Delete(u => ids.Contains(u.UserID));
Entity Framework修改數據
修改某個用戶的屬性,使用Subsonic的代碼:
XUserCollection users = new Select().From<XUser>() .Where(XUser.IdColumn).In(ids) .ExecuteAsCollection<XUserCollection>(); foreach (XUser user in users) { user.Enabled = enabled; } users.BatchSave();
使用EF的代碼也是類似的,先將需要修改數據的加載到內存中,然后修改:
DB.Users.Where(u => ids.Contains(u.UserID)).ToList().ForEach(u => u.Enabled = enabled); DB.SaveChanges();
使用 EntityFramework.Extended 后,代碼就更加簡單了,并且減少了數據庫連接次數:
DB.Users.Update(u => ids.Contains(u.UserID), u => new User { Enabled = enabled });
Entity Framework查詢數據(數據庫分頁)
查詢用戶列表,并進行數據庫分頁的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); } // 過濾啟用狀態 if (rblEnableStatus.SelectedValue != "all") { q.And(XUser.EnabledColumn).IsEqualTo(rblEnableStatus.SelectedValue == "enabled" ? true : false); } // 在查詢添加之后,排序和分頁之前獲取總記錄數 // Grid1總共有多少條記錄 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的代碼也很簡單:
var q = DB.Users.Include(u => u.Dept); // 在用戶名稱中搜索 string searchText = ttbSearchMessage.Text.Trim(); if (!String.IsNullOrEmpty(searchText)) { q = q.Where(u => u.Name.Contains(searchText) || u.ChineseName.Contains(searchText) || u.EnglishName.Contains(searchText)); } // 過濾啟用狀態 if (rblEnableStatus.SelectedValue != "all") { q = q.Where(u => u.Enabled == (rblEnableStatus.SelectedValue == "enabled" ? true : false)); } // 在查詢添加之后,排序和分頁之前獲取總記錄數 Grid1.RecordCount = q.Count(); // 排列 q = q.OrderBy(u => u.Name); // 數據庫分頁 q = q.Skip(Grid1.PageIndex * Grid1.PageSize).Take(Grid1.PageSize); Grid1.DataSource = q; Grid1.DataBind();
和Subsonic的代碼類似,首先添加Where查詢條件,然后數據庫查詢獲取總記錄數(q.Count),之后進行排序,最后是數據庫分頁。
美中不足的是排序,Entity Framework的OrderBy默認不支持字符串表示的列名!
沒關系,下個版本我們會介紹如何向OrderBy傳遞字符串參數。
下載或捐贈AppBox
1. AppBox v2.1 是免費軟件,免費提供下載:http://fineui.com/bbs/forum.php?mod=viewthread&tid=3788
2. AppBox v3.0 是捐贈軟件,你可以通過捐贈作者來獲取AppBox v3.0的全部源代碼(http://fineui.com/donate/)。
文章列表