[Asp.Net] 使用ObjectContainerDataSource,透過Service的Interface存取資料

[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

48

而如果要處理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