Populating Object with Data VB.net - asp.net

I'm looking to populate an object then display the data to labels.
I've created a Student Class:
Public Class student
Public Dim sNum As Integer
Public sName As String
Public Sub New(ByVal sNum As Integer)
MyBase.New()
Me.sNum = sNum
End Sub
I've got a database class that I want to use to populate this.
Public Function populateStudent() As Object
Dim ObjStudent As New student(1)
ObjStudent.sName = "Bitz"
Return ObjStudent
End Function
Obviously this is just a step, eventually I'll be querying the database to populate the data, but I want to get this working first so I know I'm creating this correctly.
In my main class attached to my .aspx I want to be able to do
lblStudentName.Text = ObjStudent.sName
Am I going about this correctly, or is there a better way?

You need not have
MyBase.New()
because you don't have a explicit base class.
The return type of populateStudent() of Object does not make much sense; it should be either a list of Student if you are planning to return a collection of student after querying the db. if you are planning on populating the view from this method itself, then it should be a Sub returning nothing and not a Function.
Otherwise everything else looks okay.
EDIT:
Sounds like you need something like this.
Public Function populateStudent(Id as String) As student
Dim ObjStudent As New student(1)
ObjStudent.sName = "Bitz"
Return ObjStudent
End Function

Close. You'll want to set the .Text property on the Label control:
lblStudentName.Text = ObjStudent.sName
(which you have since edited your question to contain... it often bothers me that SO doesn't show that something was edited if the edit is very soon after the initial post)
As for a "better way" just remember that there are many, many ways to do just about anything. "Better" is very relative and depends on other factors not present in the code you have so far. As of now, you have a method which returns an instance of an object (similar to the Factory pattern, feel free to research more on that and other patterns) and you use properties on that object to populate data fields in the UI. Pretty straightforward, nothing wrong with it.
As the system grows and the problem domain becomes more complex, there will be more definition of "good design" vs. "bad design." But in just getting started, this is perfectly fine.

Related

Is it bad to instantiate request and response objects in other functions?

I could not find a similar question, and this could be a dumb question, not sure, I couldn't figure out what keywords to search for.
For example, we have some sort of request/response pair for accessing information from the database (forgive me, using VB .NET at work, not my choice, so I'm just staying consistent)
Public Class ItemAddRequest
Public param1 As String = ""
Public param2 As String = ""
End Class
Public Class ItemAddResponse
Public returnParameter As MyItemObject = ""
Public Function Invoke(req As ItemAddRequst)
' SQL Queries go here
' Build my returnParameter
End Function
End Class
So these are used for the front end to get information to display on the front end, but is it bad to use these somewhere else in your code for the sole purpose of getting that info or adding that info? Generally you would want to modularize (invented word) that and use methods of my MyItemObject to do this, but we already have a large collection of things that would need to be changed so we are not doing that, at least for now. So for example we are doing something like this
Public Class ParentItemAddRequest
Public param1 As String = ""
Public param2 As String = ""
End Class
Public Class ParentItemAddResponse
Public returnParameter As MyParentItemObject = ""
Public Function Invoke(req As ParentItemAddRequest)
' SQL Query goes here to add parent
' Now also need to add a regular MyItemObject
Dim itemReq as new ItemAddRequest()
Dim itemResp as new ItemAddResponse()
itemReq.param1 = 'whatever
itemReq.param2 = 'whatever
itemResp.Invoke(itemReq)
me.returnParameter = itemResp.returnParameter
End Function
End Class
Doing this seems to work fine, but what kind of problems could we anticpate to cause? Or is this a completely normal thing? Seems odd to us. Thanks for the help.
If this code works than not much is wrong. If it aint broke then dont fix it. That being said, the only thing wrong with this code, i think, is that it uses wrong patterns. It just looks wrong. The only problem it would create is that it would confuse the hell out of new hires. Another serious implication of working this way is that the Class is now responsible for two things (1) declaring the data contract (2) defining the algo to fill it. This mixup is frowned upon according to SOLID principles. The mixup of responsibilities make it difficult to do unit testing and impact analysis.
When I find a Request class and Response class, the immediate assumption is that you guys are using the DTO pattern. The classes are assumed to be data contracts because of their naming convention. Now, the dtos are supposed to be simple POCOs devoid of any business logic. This is so that you can put all such classes in a seperate dll and different clients can use the shared data structures. So I wont be expecting the Invoke method there. I would expect that the dto is filled at the DAL layer either by handcrafted sqls in a DAO class or via some orm like entity framework.
With handcrafted sqls, I would expect a set of classes like Class ParentItemDAO with methods like Function Add(req As AddParentItemRequest) As AddParentItemResponse. Similarly I would expect a method Function GetParentItemById returning either a business object or a dto.

when to use shared variables

I have built a class which is instantiated many times in a list using vb.net. I want to persist an ID across all instantiations of my class. It's a list of questions which will all have one questionnaire ID. So I can do this whilst assigning the id to each question in the list. Ideally I would like to just assign the ID once and have it available in all the list objects.
So here is my shared member of a class along with property procedure for accessibilty.
Public Class Questions
Private Shared _questionnaireUID As Integer
Public Shared Property QuestionnaireUID() As Integer
Get
Return _questionnaireUid
End Get
Set(ByVal value As Integer)
_questionnaireUid = value
End Set
End Property
End Class
I started to use a vb.net shared class level variable and assigned through a property procedure. This seemed like the right approach, although now I have built it I can see that the shared variable is accessible throughout the entire application.
So like this for instantiation and assignment.
Questions.QuestionnaireUID = CInt(questionnaireUID)
I dont even need to instantiate the class. So I now just have a global variable. to get around this I would use a class level variable instead of. I wondered if there is another way to just make the variable shared across the class and it's instantiated objects without assigning to each object and without making it available across the entire application. Is there a step I am missing.
Thanks for any advice.
I am C# but that is not how I would go about it.
Have a class for the questionnaire
public class Questionnaire
{
public Int ID { get; private set; }
public List<Question> Questions { get; set; }
}
I think a shared (static) is really useful if you want to share something in the whole application.
If I understand you right, you indeed have a class and would like to share one ID, but this ID is not interesting for the whole application but only for a questionnaire (a list of questions). For this, using shared is bad, because you will have to take care of the cleaning of this value once you're finished.
My question is, why do you instantiate the question list every time that you have a new question? Why don't putting the question list as a singleton?
Just because the private field is Shared, that does not mean that the property that accesses it also has to be Shared. For instance, you could do this:
Public Class Questions
Private Shared _questionnaireUID As Integer
Public Property QuestionnaireUID() As Integer ' Note, this is not Shared
Get
Return _questionnaireUid
End Get
Set(ByVal value As Integer)
_questionnaireUid = value
End Set
End Property
End Class
When you do that, all Questions objects will always share the same value for that property, but the value will not be accessible through the class (without instantiating an object).
However, it's worth pointing out that, while that does encapsulate the value a little better as far as scope is concerned, it's still global state. It doesn't really avoid most of the problems which are caused by having global variables. The objects of that class will still behave in potentially unpredictable ways just as with any other kind of global state. It also makes it so that you cannot have Questions objects working on two different ID's at the same time.
As an alternative, you may want to look into injecting the ID in the Questions class' constructor. If passing it in each time you create one is too much of a pain, you could make it easier with a factory, for instance:
Public Class QuestionsFactory
Public Sub New(questionnaireId As Integer)
_questionnaireId = questionnaireId
End Sub
Private _questionnaireId As Integer
Public Function NewQuestions() As Questions
Return New Questions(_questionnaireId)
End Function
End Class

3 tier application pattern suggestion

I have attempted to make my first 3 tier application. In the process I have run into one problem I am yet to find an optimal solution for.
Basically all my objects use an IFillable interface which forces the implementation of a sub as follows
Public Sub Fill(ByVal Datareader As Data.IDataReader) Implements IFillable.Fill
This sub then expects the Ids from the datareader will be identical to the properties of the object as such.
Me.m_StockID = Datareader.GetGuid(Datareader.GetOrdinal("StockID"))
In the end I end up with a datalayer that looks something like this.
Public Shared Function GetStockByID(ByVal ConnectionString As String, ByVal StockID As Guid) As Stock
Dim res As New Stock
Using sqlConn As New SqlConnection(ConnectionString)
sqlConn.Open()
res.Fill(StockDataLayer.GetStockByIDQuery(sqlConn, StockID))
End Using
Return res
End Function
Mostly this pattern seems to make sense. However my problem is, lets say I want to implement a property for Stock called StockBarcodeList. Under the above mentioned pattern any way I implement this property I will need to pass a connectionstring to it which obviously breaks my attempt at layer separation.
Does anyone have any suggestions on how I might be able to solve this problem or am I going about this the completely wrong way? Does anyone have any suggestions on how I might improve my implementation? Please note however I am deliberately trying to avoid using the dataset in any form.
Use the app.config file for your connection string.
Is there a particular reason you pass ConnectionString at all? It seems like a configuration value to me? So using something like a constant (or a Config singleton) might be a better idea.

How to use SQL from asp.net?

Building a relatively simple website, and need to store some data in the database (mainly authentication, but there's some per-user stuff). I've worked on a couple of websites previously, and used database there too, but never liked the way I accessed the database.
The way I usually did this was by having a SqlMethods.cs, which basically was a static class with a whole lot of static methods such as bool CheckUserExistence(string username, string password) and SqlDataReader GetJobListings(int advertiserId), each of which was essentially "open connection, call a sproc, return what it returns". This approach seems un-natural to me, however. I cant quite put my mind to what I want it to look like, but this seems...weird.
So, my question is this: how do you access the database from your asp.net projects?
I am using SQL2005. I also dont think I'll need an ORM of any kind, since there really isnt that much to get from the DB, but maybe its easier with one? Suggest something.
Thanks!
Edit:I currently decided to just create a static class Sql that will have a number of sql-related methods (such as ExecuteReader(sprocName, params[]), etc) that will call the sproc with the given parameters and just return the DataReader.
Then, have classes for specific functionality, such as Authentication with methods like CheckUserExistence(username, password) and LogoffUser(session). These methods would just call Sql.ExecuteReader("sp_Auth_CheckUserExistence", _some_params_here_) and process the result as needed.
I don't know if thats good or bad, but it seems to work for me at the moment. Plus, I like the way it feels - its all nicely separated functionality-wise.
So, any more suggestions?
Check out Linq to SQL or Linq to Entities:
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
http://msdn.microsoft.com/en-us/library/bb386964.aspx
The simplest way to do it is to create a data access class for each table in your database. It should have private variables and public properties for all of the columns in the table and the methods you describe should fill the internal variables (or use them to update the database).
Public Class MyTable
Private _id As Integer
Private _Name as String
Public ReadOnly Property ID As Integer
' Regular stuff here
End Property
Public Property Name As String
' Regular stuff here
End Property
Public Sub Load()
' Call SQL and get a data reader.
' Set _id and _Name from the data reader.
End Sub
End Class
Then, in your other code:
Dim mt As New MyTable
mt.Load()
' Now use mt.ID and mt.Name to access the data

Using a ref to pass GridView columns to a method

So I'm working on this VB to C# web application migration and came across an issue that I'm hoping there is an easy work around for. There's a webform that uses the GridView control. In code, it passes the columns collection into a method that adds columns dynamically based on the user, permissions, and environment. So, the columns were passed into the function in VB using ByRef like so:
Public Sub PopulateColumns(ByRef ColumnCollection As DataControlFieldCollection)
'Do something
End Sub
Now in C#, I've used the ref keyword, but the columns collection doesn't have a setter. What's my quickest workaround for this? I'm going to be converting this over to a jQuery grid soon so I'm not concerned with best practices, but rather just getting it to work.
Here it is in C#:
public void PopulateColumns(ref DataControlFieldCollection columnCollection)
{
// Something here
}
which is called like this...
.PopulateColumns(ref EmployeeGridView.Columns)
The collection is already ByRef, so you do not need the ref argument.
So, unless I'm having a blonde moment, you just have to do:
public void PopulateColumns(DataControlFieldCollection columnCollection)
{
// Something here
}
.PopulateColumns(EmployeeGridView.Columns)
Tested and working.

Resources