No parameterless constructor error for dataview

  • Thread starter Thread starter Julia B
  • Start date Start date
J

Julia B

Apologies for the cross posting. I posted to the datagrid group a couple of
weeks ago, but haven't got an answer so am trying here.

I've got a 3 tiered application in .net 2.0 and am using dataviews for the
first time.

(tier 1) web layer with forms - RC_Web_AccountMonitor
(tier 2) business logic - RC_BL_AccountMonitor
(tier 3) data connection - RC_DL_AccountMonitor

I'm trying to load some data into a dataview, with a datasource that is an
ObjectDataSource object and getting the message "No parameterless constructor
defined for this object". Basically the webform is in tier 1, which calls a
function called DisplayUsers in tier 2 (within the Users class), which in
turn calls a couple of functions/subs in tier 3. This is how it's set up.

The ObjectDataSource object has
a TypeName of RC.RC_BL_AccountMonitor.User
a SelectMethod of DisplayUsers
and a Parameter Name of userCurrent with value of 1
Class BL_User looks like this:

Namespace RC_BL_AccountMonitor

Public Class User
'This class is used for displaying & updating user records.
'It is not used for getting the current user's rights which is done
'in the BL_AppAdmin class


#Region "Fields"
'These field names map to the fields within the Users table except the
'fields don't have a _ prefix
Private _userID As Integer
Private _forename As String
Private _surname As String
Private _middleInitial As String
Private _roleID As Integer
Private _networkID As String
Private _emailAddress As String
Private _deptID As Integer
Private _startDate As Date
Private _leaveDate As Date
Private _temp As Boolean
Private _hrReceivedEmails As Boolean
Private _facilitiesReceivedEmails As Boolean
Private _userCurrent As Boolean

#End Region

#Region "Properties"
Public Property UserID() As Integer
Get
Return _userID
End Get
Set(ByVal value As Integer)
_userID = value
End Set
End Property

Public Property Forename() As String
Get
Return _forename
End Get
Set(ByVal value As String)
_forename = value
End Set
End Property

Public Property Surname() As String
Get
Return _surname
End Get
Set(ByVal value As String)
_surname = value
End Set
End Property

Public Property MiddleInitial() As String
Get
Return _middleInitial
End Get
Set(ByVal value As String)
_middleInitial = value
End Set
End Property

Public Property RoleID() As Integer
Get
Return _roleID
End Get
Set(ByVal value As Integer)
_roleID = value
End Set
End Property

Public Property NetworkID() As String
Get
Return _networkID
End Get
Set(ByVal value As String)
_networkID = value
End Set
End Property

Public Property EmailAddress() As String
Get
Return _emailAddress
End Get
Set(ByVal value As String)
_emailAddress = value
End Set
End Property

Public Property DeptID() As Integer
Get
Return _deptID
End Get
Set(ByVal value As Integer)
_deptID = value
End Set
End Property

Public Property StartDate() As Date
Get
Return _startDate
End Get
Set(ByVal value As Date)
_startDate = value
End Set
End Property

Public Property LeaveDate() As Date
Get
Return _leaveDate
End Get
Set(ByVal value As Date)
_leaveDate = value
End Set
End Property

Public Property Temp() As Boolean
Get
Return _temp
End Get
Set(ByVal value As Boolean)
_temp = value
End Set
End Property

Public Property HRReceivedEmails() As Boolean
Get
Return _hrReceivedEmails
End Get
Set(ByVal value As Boolean)
_hrReceivedEmails = value
End Set
End Property

Public Property FacilitiesReceivedEmails() As Boolean
Get
Return _facilitiesReceivedEmails
End Get
Set(ByVal value As Boolean)
_facilitiesReceivedEmails = value
End Set
End Property

Public Property UserCurrent() As Boolean
Get
Return _userCurrent
End Get
Set(ByVal value As Boolean)
_userCurrent = value
End Set
End Property

#End Region

#Region "Constructors"
Public Sub New(ByVal UserID As Integer, ByVal Forename As String, _
ByVal Surname As String, ByVal MiddleInitial As
String, _
ByVal RoleID As Integer, ByVal NetworkID As String, _
ByVal EmailAddress As String, ByVal DeptID As
Integer, _
ByVal StartDate As Date, ByVal LeaveDate As Date, _
ByVal Temp As Boolean, ByVal HRReceivedEmails As
Boolean, _
ByVal FacilitiesReceivedEmails As Boolean, _
ByVal UserCurrent As Boolean)

_userID = UserID
_forename = Forename
_surname = Surname
_middleInitial = MiddleInitial
_roleID = RoleID
_networkID = NetworkID
_emailAddress = EmailAddress
_deptID = DeptID
_startDate = StartDate
_leaveDate = LeaveDate
_temp = Temp
_hrReceivedEmails = HRReceivedEmails
_facilitiesReceivedEmails = FacilitiesReceivedEmails
_userCurrent = UserCurrent
End Sub

#End Region

#Region "OtherVariables"
Private _ConnectionStr As String = ""
#End Region

Public Sub New(ByVal ConnectionStr As String)
_ConnectionStr = ConnectionStr
End Sub

Public Function DisplayUsers(ByVal userCurrent As Integer) As DataSet
'This function returns a dataset which displays a list of users
'it uses the dl level getdatasetfromsp function

Dim dsDataGrid As DataSet

With New RC.RC_DL_AccountMonitor.DL_Connection(_ConnectionStr)
.AddParameter("@userCurrent", SqlDbType.Int, 0, userCurrent)
dsDataGrid = .GetDatasetFromSP("sp_AllCurrentUsers")
End With

Return dsDataGrid

End Function

End Class

End Namespace

The db level DL_Connection class looks like this:
Imports System.Data.SqlClient

Namespace RC_DL_AccountMonitor

Public Class DL_Connection

Private _ParamList As SqlParameterCollection
Private _MyComm As New SqlCommand

Private _ConnectionStr As String = ""


Public Sub New(ByVal ConnectionStr As String)
_ConnectionStr = ConnectionStr
End Sub

Public Function GetDatasetFromSP(ByVal SPName As String) As DataSet
Dim Myds As New DataSet
Dim ConnectionStr As String = _ConnectionStr
Dim Myconn As New SqlConnection(ConnectionStr)
Dim MyAdapter As New SqlDataAdapter(_MyComm)
_MyComm.CommandType = CommandType.StoredProcedure
_MyComm.CommandText = SPName

Myconn.Open()
Try
_MyComm.Connection = Myconn
MyAdapter.Fill(Myds, "Results")
Catch ex As Exception
'#### need to add something here
Finally
Myconn.Close()
End Try

Return Myds

End Function

Public Sub AddParameter(ByVal ParamName As String, ByVal paramType
As Data.SqlDbType, ByVal Paramlenght As Int16, ByVal ParamValue As String)
_MyComm.Parameters.Add(ParamName, paramType, Paramlenght)
_MyComm.Parameters(ParamName).Value = ParamValue
End Sub

End Class

End Namespace

Stored procedure sp_AllCurrentUsers is written like this (and works):

ALTER PROCEDURE sp_AllCurrentUsers
/*
Name: sp_AllCurrentUsers
Description: Used to display all current users for IT personnel for user
management
*/

(
@userCurrent int
)
AS
SELECT Surname, MiddleInitial, Forename, Role, NetworkID, EmailAddress,
Dept, StartDate, LeaveDate, Temp, HRReceivedEmails, FacilitiesReceivedEmails
FROM
(Users LEFT JOIN Roles ON Users.RoleID = Roles.RoleID)
LEFT JOIN Departments ON Users.DeptID = Departments.DeptID
WHERE UserCurrent=@usercurrent
ORDER BY Surname
RETURN

If anyone has any ideas why this might not be working I'd be very grateful.
Thanks in advance.
Julia
 
Apologies for the cross posting. I posted to the datagrid group a couple of
weeks ago, but haven't got an answer so am trying here.
I'm trying to load some data into a dataview, with a datasource that is an
ObjectDataSource object and getting the message "No parameterless constructor
defined for this object". Basically the webform is in tier 1, which calls a
function called DisplayUsers in tier 2 (within the Users class), which in
turn calls a couple of functions/subs in tier 3. This is how it's set up.

Usually that errormessage means that you derived a class from a
baseclass that has no parameterless constructors.
Always when you call a constructor, a constructor of a baseclass is
also executed (before your own construcor executes). If you don't call
one explicitly, the parameterless constructor is called automatically.

I don't know what the VB syntax is. In C# it would be something like:

class MyClass: MyBaseClass
{
// MyBaseClass is a baseclass for this class and
// has a constructor with one 'int' parameter

// constructor that explicitly calls a constructor of the baseclass
public MyClass(int aValue): base(aValue)
{
// further processing as needed
}
}


Hans Kesting
 
I don't think it's that. My class is not derived from a base class. Any other
ideas?

Thanks
Julia
 
Julia B was thinking very hard :
I don't think it's that. My class is not derived from a base class. Any other
ideas?

Thanks
Julia

No specific ones, just general questions:
* When and where do you get that error exactly?
* Compile time/runtime?
* Source line
* Is there a stacktrace that can help you pinpoint the error?
* Can you shorten that example so that we don't have to wade through
all sorts of properties that are probably not involved in the problem?
If the system complains about a constructor, then SQL code is probably
not the problem.
See also http://www.yoda.arachsys.com/csharp/complete.html

Hans Kesting
 
Hans, apologies for putting so much code on the posting, I've been moaned at
in the past for not putting enough. Can't win eh? :-)

Here are the answers anyway....

The error happens at runtime
There is no source line - it happens after the form load
Here's the stack trace:

[MissingMethodException: No parameterless constructor defined for this
object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean
publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor,
Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean
fillCache) +103
System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean
skipVisibilityChecks, Boolean fillCache) +261
System.Activator.CreateInstance(Type type, Boolean nonPublic) +66

System.Web.UI.WebControls.ObjectDataSourceView.InvokeMethod(ObjectDataSourceMethod method, Boolean disposeInstance, Object& instance) +127

System.Web.UI.WebControls.ObjectDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments) +2040
System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments,
DataSourceViewSelectCallback callback) +17
System.Web.UI.WebControls.DataBoundControl.PerformSelect() +149
System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +70
System.Web.UI.WebControls.GridView.DataBind() +4
System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +82
System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls()
+69
System.Web.UI.Control.EnsureChildControls() +87
System.Web.UI.Control.PreRenderRecursiveInternal() +41
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1360

And a shortened example which is still causing the problem:

Layer1 - RC_Web_AccountMonitor
Form Users.aspx has a dataview
Dataview has ObjectDataSource of dgDataSource
dgDataSource has TypeName of RC.RC_BL_AccountMonitor.BL_AppAdmin,
SelectMethod of FillDataGrid and SelectParameter of Name spName, Value
sp_UsersList.

Layer 2 - RC_BL_AccountMonitor
Public Class BL_AppAdmin

Private _ConnectionStr As String = ""

Public Sub New(ByVal ConnectionStr As String)
_ConnectionStr = ConnectionStr
End Sub

Public Function FillDataGrid(ByVal spName As String) As
DataSet
Dim dsDataGrid As DataSet

'this function returns a dataset that fills an unparametered
datagrid
With New RC.RC_DL_AccountMonitor.DL_Connection(_ConnectionStr)
dsDataGrid = .GetDatasetFromSP(spName)
End With

Return dsDataGrid

End Function

Layer 3 - RC_DL_AccountMonitor
Public Class DL_Connection

Private _ParamList As SqlParameterCollection
Private _MyComm As New SqlCommand

Private _ConnectionStr As String = ""

Public Sub New(ByVal ConnectionStr As String)
_ConnectionStr = ConnectionStr
End Sub

Public Function GetDatasetFromSP(ByVal SPName As String) As DataSet
Dim Myds As New DataSet
Dim ConnectionStr As String = _ConnectionStr
Dim Myconn As New SqlConnection(ConnectionStr)
Dim MyAdapter As New SqlDataAdapter(_MyComm)
_MyComm.CommandType = CommandType.StoredProcedure
_MyComm.CommandText = SPName

Myconn.Open()
Try
_MyComm.Connection = Myconn
MyAdapter.Fill(Myds, "Results")
Catch ex As Exception
'to be developed
Finally
Myconn.Close()
End Try

Return Myds

End Function

The stored procedure now looks like this (parameter has been removed for
simplicity)

ALTER PROCEDURE sp_UsersList
AS
SELECT Surname, MiddleInitial, Forename, Role, NetworkID, EmailAddress,
Dept, StartDate, LeaveDate, Temp, HRReceivedEmails, FacilitiesReceivedEmails
FROM
(Users LEFT JOIN Roles ON Users.RoleID = Roles.RoleID)
LEFT JOIN Departments ON Users.DeptID = Departments.DeptID
WHERE UserCurrent=1
ORDER BY Surname
RETURN


That's it I think.
Thanks in advance
Julia
 
Solved it. I had to rewrite my classes in my business & datalayer changing
their constructors.

Julia
 
Julia would you mind sharing the key points of your fix? I'm running into the
same problem here. I have a default constructor in my data entity, the BL is
all Shared subs - no instantiation, the data access has a default
constructor. I tried adding some data and a constructor to the BL class, but
it didn't help. What did you do to your c'tor to make it work?

TIA
Mike
 
Mike, apologies for the long delay in responding, I didn't read your post
till today. Anyway, if I can still help here's what I did (with a simpler
example than when I originally posted):

Tier 1 - web layer
My object datasource properties are:

TypeName RC.RC_Web_AccountMonitor.CommonUtilities
SelectMethod FillDataGrid
Select Parameters Name spName Value sp_DepartmentList

Tier 2 - business layer

Imports System.Data.SqlClient

Namespace RC_Web_AccountMonitor

Public Class CommonUtilities
Public Sub New()

End Sub

Public Function FillDataGrid(ByVal spName As String) As DataSet
Dim dsDataGrid As DataSet

'this function returns a dataset that fills an unparametered
datagrid
With New DBConnection
dsDataGrid = .GetDatasetFromSP(spName)
End With
Return dsDataGrid

End Function

End Class

End Namespace

Tier 3 - data layer

Imports System.Data.SqlClient

Public Class DBConnection

Private _ParamList As SqlParameterCollection
Private _MyComm As New SqlCommand

Private _ConnectionStr As String =
ConfigurationManager.ConnectionStrings("Conn").ToString

'shared connection
Dim conn As New SqlConnection(_ConnectionStr)

Public Sub New()

End Sub

Public Function GetDatasetFromSP(ByVal SPName As String) As DataSet

Dim Myds As New DataSet

Dim MyAdapter As New SqlDataAdapter(_MyComm)
_MyComm.CommandType = CommandType.StoredProcedure
_MyComm.CommandText = SPName

_MyComm.Connection = conn
Try
MyAdapter.Fill(Myds, "Results")
Catch ex As Exception
System.Web.HttpContext.Current.Session("DBError") = "True"
System.Web.HttpContext.Current.Session("DBEx") = ex.ToString
Finally

End Try
Return Myds

End Function

End Class

End Namespace

This works fine. I hope this helps.
Julia
 
Hi Julia,

Thanks for taking the time to get back to me. I found a different solution
to mine. If I remember correctly the reason for my error message was that I
was passing the object by reference in one of the data access methods by
mistake.

Mike
 
Back
Top