自訂OpenAccessLinqDataSource執行時期的OpenAccessContext

  • 1485
  • 0

自訂OpenAccessLinqDataSource執行時期的OpenAccessContext

OpenAccess快速入門03 中,「關於建立 OpenAccessContext 的方式」小節中,我們有看到下面的圖:

134458

所以我們知道,OpenAccessContext 可以使用帶有參數的建構式,但是當我們使用 OpenAccessLinqDataSource 控制項時,他預設會使用無參數建構子來創建 OpenAccessContext,所以如果我們需要使用帶參數的建構子,甚至在執行時期換成完全不同的 OpenAccessContext,該怎麼做?

Ps. 換成完全不同的 OpenAccessContext 時,請務必考慮這樣會不會造成後續資料存取的問題。

或者,我們想要讓頁面上多個 OpenAccessLinqDataSource 控制項,在同一次 ASP.NET 生命週期時,共用相同的 OpenAccessContext,該怎麼做?

答案是:透過 OpenAccessLinqDataSource 控制項的 ContextCreating 事件時,自行指定 ObjectInstance。

但這裡有個地方要注意:預設的情況下,OpenAccessLinqDataSource 在每次 CRUD 執行完成後,會把自己的 OpenAccessContext 給消滅(Dispose)掉,但是如果我們在 ContextCreating 事件中,重新指定 ObjectInstance,則 OpenAccess ORM 不會幫我們做 Dispose 的動作。

以下為自行指定 ObjectInstance 的範例程式,我們建立一個 MultiOALDSUsingSameDataContext.aspx 頁面,放置:

  • 一個 Label,名為 lblCount,顯示 OpenAccessLinqDataSource 控制項用了幾個不同的 OpenAccessContext。
  • 兩個 GridView,名稱不重要,反正只是為了讓兩個 OpenAccessLinqDataSource 執行查詢顯示結果用的。
  • 兩個 OpenAccessLinqDataSource,一個查 Orders,一個查 Customers。

然後在 vb 程式碼中,於 Page_Load 事件時,我們建立一個新的 OpenAccessContext,並在 OpenAccessLinqDataSource 的 ContextCreating 事件時,把這個 OpenAccessContext 指派給 ObjectInstance。

另外,為了驗證上述說法:「OpenAccess ORM 在執行時期自行指派 OpenAccessLinqDataSource 控制項的 OpenAccessContext 時,不會幫我們做 OpenAccessContext Dispose 的動作。」所以我們在 OpenAccessLinqDataSource 的 ContextDisposing 事件中,判斷目前控制項所持有的 OpenAccessContext 和另一個 OpenAccessLinqDataSource 控制項所持有的 OpenAccessContext 是否相同,不同的話,計數次就加 1,所以範例程式有兩個 OpenAccessLinqDataSource,在自行指派的情況下,應該只會有一個 OpenAccessContext

MultiOALDSUsingSameDataContext.aspx:

<%@ Register assembly="Telerik.OpenAccess.Web.40" namespace="Telerik.OpenAccess.Web" tagprefix="telerik" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>兩個OpenAccessLinqDataSource用相同DataContext</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>    
        建立幾次 OpenAccessContext:<asp:Label ID="lblCount" runat="server" Text="0"></asp:Label>
        <br />
        最新訂單:<br />
        <asp:GridView ID="gvNewestOrder" runat="server" AutoGenerateColumns="False" DataKeyNames="ORDERID" DataSourceID="oasrcOrders">
            <Columns>
                <asp:BoundField DataField="ORDERID" HeaderText="ORDERID" ReadOnly="True" SortExpression="ORDERID" />
                <asp:BoundField DataField="CUSTOMERID" HeaderText="CUSTOMERID" SortExpression="CUSTOMERID" />
            </Columns>
        </asp:GridView>
        <br />
        最新顧客名單(LEO打頭):<br />
        <asp:GridView ID="gvList" runat="server" AutoGenerateColumns="False" DataKeyNames="CUSTOMERID" DataSourceID="oasrcCustomers" PageSize="5">
            <Columns>
                <asp:BoundField DataField="CUSTOMERID" HeaderText="CUSTOMERID" ReadOnly="True" SortExpression="CUSTOMERID" />
                <asp:BoundField DataField="COMPANYNAME" HeaderText="COMPANYNAME" SortExpression="COMPANYNAME" />
            </Columns>
        </asp:GridView>
        <asp:Label ID="lblLog" runat="server"></asp:Label>
        <telerik:OpenAccessLinqDataSource ID="oasrcOrders" Runat="server" ContextTypeName="OALinqDataSourceWeb01.NWModel" EnableInsert="True" EntityTypeName="" ResourceSetName="Orders" OrderBy="ORDERID desc" />
        <telerik:OpenAccessLinqDataSource ID="oasrcCustomers" runat="server" ContextTypeName="OALinqDataSourceWeb01.NWModel" EntityTypeName="" ResourceSetName="Customers" OrderBy="CUSTOMERID desc" EnableInsert="True" Where="CUSTOMERID.StartsWith(@CUSTOMERID)" >
            <WhereParameters>
                <asp:Parameter DefaultValue="LEO" Name="CUSTOMERID" Type="String" />
            </WhereParameters>
        </telerik:OpenAccessLinqDataSource>
        </div>
    </form>
</body>
</html>

MultiOALDSUsingSameDataContext.aspx.vb:


Public Class MultiOALDSUsingSameDataContext
    Inherits System.Web.UI.Page
    Private tracer As MyNorthwindTraceListener
    Private myCxt As NWModel
    Private dataSourceCxt As NWModel
    Private createCount As Integer = 0

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If tracer Is Nothing Then
            tracer = New MyNorthwindTraceListener(New StringBuilder())
        End If
        If myCxt Is Nothing Then
            myCxt = New NWModel(ConfigurationManager.ConnectionStrings("XE11G").ConnectionString)
        End If
    End Sub

    Private Sub oasrc_ContextCreating(sender As Object, e As Telerik.OpenAccess.Web.OpenAccessLinqDataSourceContextEventArgs) Handles oasrcCustomers.ContextCreating, oasrcOrders.ContextCreating
        e.ObjectInstance = myCxt
    End Sub

    Private Sub oasrc_ContextCreated(sender As Object, e As Telerik.OpenAccess.Web.OpenAccessLinqDataSourceStatusEventArgs) Handles oasrcCustomers.ContextCreated, oasrcOrders.ContextCreated
        If e.Result.Equals(dataSourceCxt) = False Then
            createCount += 1
            dataSourceCxt = e.Result
        End If
        lblCount.Text = createCount
    End Sub

    Private Sub oasrcOrders_Selecting(sender As Object, e As Telerik.OpenAccess.Web.OpenAccessLinqDataSourceSelectEventArgs) Handles oasrcOrders.Selecting
        e.Arguments.MaximumRows = 1
    End Sub

    Private Sub oasrcCustomers_Selected(sender As Object, e As Telerik.OpenAccess.Web.OpenAccessLinqDataSourceStatusEventArgs) Handles oasrcCustomers.Selected, oasrcOrders.Selected
        lblLog.Text = tracer.GetLogString()
    End Sub

End Class

執行結果:

164415

如果我們現在把 oasrc_ContextCreating 事件中,自行指派 OpenAccessContext 程式(e.ObjectInstance = myCxt)註解掉,就會看到計數器變成 2 囉!

--------
沒什麼特別的~
不過是一些筆記而已