在ObjectDataSource的静态方法中使用实体框架上下文
本文关键字:实体 框架 上下文 ObjectDataSource 静态方法 | 更新日期: 2023-09-27 18:01:05
我有一个现有的项目,我想对一个大型数据集使用ObjectDataSource
,该数据集为DevExpress网格分页结果。
代码示例如下所示。
在ObjectDataSource所需的静态方法中使用实体框架上下文时遇到问题。
我的问题是我得到了这个例外:
系统。ObjectDisposedException:ObjectContext实例已已处理,不能再用于需要联系
有人知道我如何更改下面的内容以支持将Entities
实例从Page传递到静态方法吗?
这是ObjectDataSource
的示例
<dx:ASPxGridView ID="DefinedReportGrid" runat="server" EnableTheming="True" Theme="Office2010Blue" EnableViewState="False"
ClientInstanceName="DefinedReportGrid" DataSourceForceStandardPaging="True" DataSourceID="ReportDataSource">
<SettingsPager PageSize="30"></SettingsPager>
</dx:ASPxGridView>
<asp:ObjectDataSource ID="ReportDataSource" runat="server" EnablePaging="True"
StartRowIndexParameterName="startRecord" MaximumRowsParameterName="maxRecords" SelectCountMethod="GetPageCount" SelectMethod="GetData"
TypeName="ReportService">
</asp:ObjectDataSource>
这是我的带有静态方法的服务类,然后可以由ObjectDataSource
使用
public class ReportService
{
[DataObjectMethod(DataObjectMethodType.Select, true)]
public static DataTable GetData(int startRecord, int maxRecords)
{
// Use EF DbContent and LINQ Query to fetch paged data, and return a DataTable
// The data is PIVOTED in the code before returning it as a DataTable
return outputTable;
}
public static List<int> GetWeeks()
{
// This also requires use of the EF DbContent
...
}
public static int GetPageCount()
{
// This also requires use of the EF DbContent
// Used to count the full data for applying the correct total Page Count
...
}
}
这是网页的代码
public partial class DefinedReport : System.Web.UI.Page
{
private Entities _modelContext = ((Global)HttpContext.Current.ApplicationInstance).Entities;
protected void Page_Init(object sender, EventArgs e)
{
...
}
protected void Page_Load(object sender, EventArgs e)
{
...
}
}
这是全局代码,在请求的开始和结束处设置实体上下文。
public class Global : HttpApplication
{
public Entities Entities { get; set; }
...
private void Application_BeginRequest(object sender, EventArgs e)
{
Entities = new Entities();
}
private void Application_EndRequest(object sender, EventArgs e)
{
if (Entities != null)
{
Entities.Dispose();
}
}
}
作为一个在VB.Net Webforms应用程序中大量使用DevX网格并使用静态/共享方法来封装各种数据访问逻辑的人,另一种方法是跳过在ASPX中创建ObjectDataSource
,而是在代码背后的Page_Load中设置网格的DataSourceID
。我发现这更易于管理和预测。
想法如下:
Private Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Using eFContext As New ApplicationEntities()
Dim requestedTransactionId As Guid = GetAndCheckQueryStringValueGuid("TransactionId")
Dim requestedTransaction As Transaction = Transaction.GetAndConfirm(eFContext, requestedTransactionId)
Dim requestedCustomers As IQueryable(Of Object) =
Customer.GetCustomersForCustomersGrid(eFContext, requestedTransaction)
CustomersGridView.DataSource = requestedCustomers
CustomersGridView.DataBind()
End Sub
我还为Page_Load中的每个请求创建了一个新的EF上下文——我没有发现与此相关的性能是一个问题,它使查找问题变得容易10倍。你可能想考虑一下,至少在开始的时候。我过去见过其他人建议将你的上下文置于会话状态,并在需要时从中获取,但这可能会导致各种难以追踪的不良行为,所以我从来没有足够的勇气尝试并使其发挥作用。
如果你遵循我的建议:如果ASPxGridView的初始加载有效,但在从一页移动到另一页、对列排序等时出现错误,那么你可能需要对网格中显示的关联实体使用一些.Includes
。
我发现了这个例子:http://www.asp.net/web-forms/tutorials/continuing-with-ef/using-the-entity-framework-and-the-objectdatasource-control,-第1部分-启动
这让我意识到,我的ReportService
类上的方法不需要是静态才能工作,这是我最初的主要问题。。我只是对ObjectDataSource
经验不足,并遵循DevExpress在此给出的示例:http://www.devexpress.com/Support/Center/Example/Details/E2672
因此,现在可以在类的范围内创建一个新的EF ObjectContext
,然后在处理该类时进行处理,这似乎对我有效。
如下所示:
public class ReportService : IDisposable
{
private bool disposedValue = false;
private Entities _modelContext = new Entities();
public DataTable GetData(int startRecord, int maxRecords)
{
...
// use _modelContext and process the data
return outputTable;
}
public List<int> GetWeeks()
{
...
// use _modelContext and process the data
}
public int GetPageCount()
{
...
// use _modelContext and process the data
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
_modelContext.Dispose();
}
}
this.disposedValue = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}