简体   繁体   English

在ObjectDataSource的静态方法中使用实体框架上下文

[英]Using an Entity Framework Context in static methods for an ObjectDataSource

I have an existing project where I want to use an ObjectDataSource for a large data set which pages the results for a DevExpress Grid. 我有一个现有项目,我想在其中使用ObjectDataSource处理大型数据集,该数据集分页显示DevExpress网格的结果。

Examples of the code are shown below. 代码示例如下所示。

I am having trouble using an Entity Framework context in static methods that are required for the ObjectDataSource. 我在ObjectDataSource所需的静态方法中使用Entity Framework上下文时遇到麻烦。

My problem is that I get this exception: 我的问题是我得到了这个异常:

System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. System.ObjectDisposedException:ObjectContext实例已被处置,不能再用于需要连接的操作。

Does anyone know how I can change the below to support passing an Entities instance from the Page to the static methods? 有谁知道我可以如何更改以下内容以支持将Entities实例从Page传递到静态方法?

This is the example of the ObjectDataSource 这是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>

This is my service class with static methods that can then be used by the 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
        ...
        }
    }

This is the code behind for the web forms page 这是Web表单页面的背后代码

    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)
        {
             ...
        }

    }

This is the global code, where the Entities context is being set on the begin and end of the request. 这是全局代码,其中在请求的开始和结束处设置了Entities上下文。

    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();
            }
        }
    }

As someone who uses the DevX grid quite a bit in a VB.Net Webforms app with static/Shared methods to encapsulate various data access logic, another approach would be to skip creating a ObjectDataSource in the ASPX and instead set up the grid's DataSourceID in the code-behind's Page_Load. 当有人在带有静态/共享方法的VB.Net Webforms应用程序中大量使用DevX网格来封装各种数据访问逻辑时,另一种方法是跳过在ASPX中创建ObjectDataSource ,而是在ASPX中设置网格的DataSourceID 。代码隐藏的Page_Load。 I founded this much more manageable and predictable. 我建立了更易于管理和可预测的方式。

Here's the idea: 这是想法:

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

I also create a new EF context for each request in Page_Load - I've not found the performance associated with this to be an issue and it makes hunting down problems 10x easier. 我还为Page_Load中的每个请求创建了一个新的EF上下文-我没有发现与此相关的性能成为问题,它使查找问题的难度提高了10倍。 You may want to consider this, at least to get started. 您可能要考虑这一点,至少要开始使用。 I've seen others in the past suggest putting your context into Session state and fetching it from there when needed, but that feels like it could cause all sorts of hard-to-track-down badness so I've never been bold enough to try and make that work. 过去我曾见过其他人建议将您的上下文置于会话状态,并在需要时从那里获取它,但这感觉可能会导致各种难以追踪的弊端,因此我从来没有足够大胆地去做。尝试使这项工作。

As a side note for if you follow my suggestion: if your initial load of the ASPxGridView works but you get errors as you move from page to page, sort columns, etc. then you may need to use some .Includes for associated entities that display in your grid. 作为旁注,如果您遵循我的建议:如果ASPxGridView的初始加载正常,但是在.Includes页移动,对列进行排序等操作时出现错误,则可能需要使用.Includes来显示相关实体在您的网格中。

I have since found this example: http://www.asp.net/web-forms/tutorials/continuing-with-ef/using-the-entity-framework-and-the-objectdatasource-control,-part-1-getting-started 此后,我找到了以下示例: http : //www.asp.net/web-forms/tutorials/continuing-with-ef/using-the-entity-framework-and-the-objectdatasource-control,-part-1-入门

which made me realise that my methods on my ReportService class don't need to be static in order for this to work, which was my main problem in the first place.. I am just not experienced enough with ObjectDataSource and was following the examples that DevExpress gave from here: http://www.devexpress.com/Support/Center/Example/Details/E2672 这使我意识到, ReportService类上的方法不需要是静态的即可起作用,这首先是我的主要问题。.我对ObjectDataSource经验不足,并且正在关注以下示例DevExpress从此处提供: http : //www.devexpress.com/Support/Center/Example/Details/E2672

So now a new EF ObjectContext can be created in the scope of the class and then Disposed of when that class is disposed and this seems to work for me. 因此,现在可以在该类的范围内创建一个新的EF ObjectContext ,然后在处置该类时将其处置,这似乎对我有用。

Like shown below: 如下图所示:

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);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM