[Asp.Net] 使用ObjectContainerDataSource,透過Service的Interface存取資料
前言
在使用ObjectDataSource時,常常會遇到一個困擾,
就是ObjectDataSource只能針對具體的Class進行設定,來選擇存取資料的方法,
而沒有辦法透過一個介面來存取資料,若日後更動Class時,還是需要大量的修改,
但在Web Client Software Factory中,有專門為了Mvp Patterns開發了一個ObjectContainerDataSource,
透過使用它,我們可以針對介面存取資料,來看看實際例子的運用吧!
實際演練
首先建立一個Service Class,以及一個簡單的Data Model,
在這邊就不介紹存取資料庫的細節了,大家可依據自己的狀況去實作
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime BirthDay { get; set; }
}
public interface IUserService
{
void DeleteUser(User user);
System.Collections.Generic.IEnumerable<User> GetUsers();
void InsertUser(User user);
void UpdateUser(User user);
}
public class UserService : Core.IUserService
{
public IEnumerable<User> GetUsers()
{
var userList = new List<User>()
{
new User(){Id=1,Name="aaa",BirthDay=DateTime.Now},
new User(){Id=2,Name="bbb",BirthDay=DateTime.Now},
new User(){Id=3,Name="ccc",BirthDay=DateTime.Now},
};
return userList;
}
public void InsertUser(User user)
{
//do something
}
public void UpdateUser(User user)
{
//do something
}
public void DeleteUser(User user)
{
//do something
}
}
再來建立一個網站,我們在View中加入Gridview以及ObjectContainerDataSource,
(ObjectContainerDataSource位於NameSpace"Microsoft.Practices.Web.UI.WebControls",可在WCSF的原始碼中取得)
特別需注意的是必須Gridview指定DataKeyNames,否則會有錯誤發生
<div>
<asp:GridView runat="server" ID="Gridview_Users" DataSourceID="UserDataSource"
AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="Id" >
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="Id" HeaderText="Id" SortExpression="Id" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="BirthDay" HeaderText="BirthDay"
SortExpression="BirthDay" />
</Columns>
</asp:GridView>
<cc1:ObjectContainerDataSource runat="server" ID="UserDataSource"
DataObjectTypeName="Core.User" />
</div>
在Page之中放一個屬性,它的型別是Service的Interface
private IUserService mUserService = new UserService();
public IUserService UserService
{
get
{
return mUserService;
}
set
{
mUserService = value;
}
}
在上面的程式碼中,你可以看到我是直接指定IUserService的實作Class,
但在實際開發時,建議使用DI Framework或工廠模式來注入實體。
接著我可以在Page_Load的時候,使用UserService來取得資料,並指定給ObjectContainerDataSource
protected void Page_Load(object sender, EventArgs e)
{
this.UserDataSource.DataSource = UserService.GetUsers();
}
按下F5執行網頁,可以看到Gridview顯示資料,我們成功的使用Interface來存取資料當作DataSource
而如果要處理Insert、Update、Delete,我們只要透過訂閱ObjectContainerDataSource的Updated、Inserted、Deleted事件,
即可取得相對應的實體,來進行資料存取。
this.UserDataSource.Updated += new EventHandler<Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceStatusEventArgs>(UserDataSource_Updated);
this.UserDataSource.Inserted += new EventHandler<Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceStatusEventArgs>(UserDataSource_Inserted);
this.UserDataSource.Deleted += new EventHandler<Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceStatusEventArgs>(UserDataSource_Deleted);
void UserDataSource_Deleted(object sender, Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceStatusEventArgs e)
{
UserService.DeleteUser((User)e.Instance);
}
void UserDataSource_Inserted(object sender, Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceStatusEventArgs e)
{
UserService.InsertUser((User)e.Instance);
}
void UserDataSource_Updated(object sender, Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceStatusEventArgs e)
{
UserService.UpdateUser((User)e.Instance);
}
如此一來,我們就連編輯,刪除,新增的功能都一次完成囉
而如果想要自訂分頁或是排序的話,我們只要透過TotalRowCount屬性設定總筆數
this.UserDataSource.TotalRowCount = UserService.GetTotalCount();
以及訂閱Selecting事件處理分頁和排序取得資料的方式
this.UserDataSource.Selecting += new EventHandler<Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceSelectingEventArgs>(UserDataSource_Selecting);
void UserDataSource_Selecting(object sender, Microsoft.Practices.Web.UI.WebControls.ObjectContainerDataSourceSelectingEventArgs e)
{
UserDataSource.DataSource = UserService.GetUsers(e.Arguments.StartRowIndex, e.Arguments.MaximumRows, e.Arguments.SortExpression);
}
即可完成囉!
結論
透過ObjectContainerDataSource,我們可以不在需要依賴Class做資料的存取,
可以透過Interface來操作資料,也增加了程式的彈性,日後要抽換也十分輕鬆愉快,
更值得一提的是它可以與Mvp Patterns很好的結合,大家有機會可以試試看喔 ^^
參考文章
How to: Use the ObjectContainerDataSource Control