I am new to EF and the Repository pattern. I understand where the problem is coming from in my code but I am not sure what is the right resolution. Here is the problem:
I have a WebForm where I am querying the DB to get one record to display. I have implemented by Business Logic Layer (BLL) and the Database Access Layer (DAL). In the WebForm I am using the following ObjectDataSource:
<asp:ObjectDataSource ID="EmployerObjectDataSource" runat="server" TypeName="IkaManagerWeb.BLL.IkaMgrBL"
DataObjectTypeName="IkaManagerWeb.BLL.IkaMgrBL"
SelectMethod="GetEmployer"
OnSelecting ="EmployerObjectDataSource_Selecting">
<SelectParameters>
<asp:Parameter Name ="username" Type="String" />
<asp:Parameter Name="version" Type="UInt16" />
</SelectParameters>
</asp:ObjectDataSource>
So at the code behind the WebForm I do the following:
public partial class WebForm1 : System.Web.UI.Page
{
private string _username;
private short _version;
protected void Page_Load(object sender, EventArgs e)
{
_username = "Lefteris";
_version = 1;
if (!Page.IsPostBack)
{
// InputStyle style = txtFirstName.DisabledStyle;
populateFields();
}
}
protected void EmployerObjectDataSource_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
e.InputParameters["username"] = _username;
e.InputParameters["version"] =_version;
}
private bool populateFields()
{
IEnumerable<Employer> empl = (IEnumerable<Employer>)EmployerObjectDataSource.Select();
System.Threading.Thread.Sleep(1000);
if (empl.Count() == 1)
{
Employer employer = empl.First();
txtAme.Text = employer.AME.ToString();
...
The problem is that as soon as I hit the line:
if (empl.Count() == 1)
above, I get an exception that the DBContext has been disposed. By stepping through the code in BLL and DAL I see that the DBContext is indeed disposed. In fact, as
EmployerObjectDataSource.Select();
returns the result, the BLL is disposed, which in turn is causing the DAL and therefore the DBContext to be disposed.
What I am thinking as a solution is to maintain a reference to the BLL for the whole execution of the PopulateFields method. So here is in the question:
Is this the right way (perhaps with a "using" block)? And if it is, then how can I get a reference to the BLL object that the EmployerObjectDataSource is instantiating in order to perform the Select?
EDIT: By stepping through the code I saw the following order of events:
Select()
method of the ObjectDataSource, the BLL object is instantiated.Dispose()
Dispose()
the DAL Dispose()
is called - this removes the DBContextSelect()
method of the ObjectDataContext returnsempl.Count()
the empl object is enumerated and since the DBContext has been removed I get the exception. EDIT: Following the request of Dmytro below, I am also providing the GetEmployer method of the BLL:
public IEnumerable<Employer> GetEmployer(string username, short version)
{
DateTime today = DateTime.Today;
IEnumerable<Employer> employers = ikaRepository.GetEmployers(username, today, version);
Debug.Assert(employers.Count() <= 1, "This is a logical Error - Can we have more than one active Employer records per user?");
return employers;
}
Note that this retrieves the record correctly.
Thank you in advance,
Lefteris
It looks like your line
IEnumerable<Employer> empl = (IEnumerable<Employer>)EmployerObjectDataSource.Select();
returns IQueryable type from Select method. This type doesn't contains real data and doesn't fetch data from db. Try use something like this
var empl = ((IEnumerable<Employer>)EmployerObjectDataSource.Select()).ToList();