自訂OpenAccessLinqDataSource執行時期的OpenAccessContext
在 OpenAccess快速入門03 中,「關於建立 OpenAccessContext 的方式」小節中,我們有看到下面的圖:
所以我們知道,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
執行結果:
如果我們現在把 oasrc_ContextCreating 事件中,自行指派 OpenAccessContext 程式(e.ObjectInstance = myCxt)註解掉,就會看到計數器變成 2 囉!
--------
沒什麼特別的~
不過是一些筆記而已