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
Related
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.
I have experience with webForms and now i am starting to learn MVC, oh boy....everything looks so different. Since my background is webForms, I just want to make sure If am doing this properly. I am pulling data (Queries, Stored Procedures etc) from MS SQL Server & Goal is to represent them within view. here is what I have done so sar.
Here is my Model
Class Product ' Just a Template
private _title
private _price
' property implementation etc
End Class
Class ProductModel ' Returns Actual Data
Function getProducts as list(of product)
' use SqlDataReader to Execute the Stored Procedure
' Populate a list(of product)
' list.add(new product(title,price))
' Return the List
end function
Function getTopProducts() as list(of products)
End Function
End Class
Now Here is my ProductsController index() ActionMethod.
Dim p as new ProductModel
return view(p)
Then within my View (Which is strongly typed for ProductModel Class), I am using a For each on Model.getProducts or Model.getTopProducts and showing the data on screen.
Now Few questions...first of all, is my approach reasonable? is it a standard way of setting up Models with MVC? If not then please correct me.
Secondly, all the examples I see online, i see people using LINQ, EF etc....however in my environment performance is very important, and i am almost always returning data using Stored procedures, so is it OK to use pure ADO.NET or using LINQ/EF can help me out in some way?
...is my approach reasonable? is it a standard way of setting up
Models with MVC? If not then please correct me.
Yes, it's best practice to use a viewmodel than work with your entities directly on your views.
is it OK to use pure ADO.NET or using LINQ/EF can help me out in some
way?
It's perfectly fine to use pure ADO.NET if you feel doing all the dirty works an ORM provides.
You approach is the one that is mostly shown when you learn about MVC. However, if you want to be a bit picky about naming convention then your ProductModel would be called ProductViewModel. This ViewModel will allow you to pass more information to View than it is available in your Product class (which is your model class). But this is insignificant although you should get used to using View with ViewModels.
As for your second question you can use anything you want as data access technology. Entity Framework is promoted by Microsoft as one of its technologies for manipulating with the information in a database. However, if you want you can use ADO.NET with stored procedures, or you can use RavenDB with its own client interface. It's really up to you.
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.
I have to send emails when a person receives a personal message on my website and for that I use a StringBuilder to create the HTML markup of the email.
also since it is required at many other places as well I have made a Shared Function (I am using VB.NET). now my only concern is that since shared functions are shared among all objects and maybe asp.net sessions, can it be possible that before one person email is being formed and another person access the same function, it would cause the data in the stringbuilder to be overwritten..
Currently my site doesn't have many users but can this become an issue in the future... Please advise me on this... Is there any better way or standard procedure to follow when using shared functions?
Also at one time I made the mistake of using a shared connection object and it would cause close if many people were to access it.
Shared functions can only access static/global variables as well as variable inside the function scope. So, if the the function is working with any number of static/shared resources then you need to synchronize between the calls to the function.
In your case, however, it doesn't sound like you're working with any shared resources, so it shouldn't be a problem.
Here's a case that illustrates the problem:
private static myCounter As Integer = 0
public shared function IncreaseCount() As Integer
myCounter += 1
for i as integer = 0 to 10 million
//'do extensive work
next
return myCounter
End Function
Imagine that you call the function for the first time, and you would expect it to return the number 1. But due to the fact that the function was called again before the first function call got to return the counter was increased once more, which means that both function calls return 2 instead of respectively 1 and 2. All the problem arrives when you want several things working on the same static resource.
Instead of using a static method you can have an EmailSender object attach to current HttpContext.This way each user will have its own EmailSender instance.
Here's the code in C# :
private static EmailSender _instance;
public static EmailSender GetEmailSender()
{
if(System.Web.HttpContext.Current != null)
{
if(! System.Web.HttpContext.Current.Items.ContainsKey("EmailSender"))
System.Web.HttpContext.Items["EmailSender"]=new EmailSender();\
return (EmailSender)System.Web.HttpContext.Current.Items["EmailSender"];
}
if(_instance==null)
_instance=new EmailSender();
return _instance;
}
It will work in web and windows application.
now every time you want to send an email you can do as follows:
GetEmailSender().SendMail(MailInfo mailInfo);
Also, if you're using VB.NET on Framework 3.5, you may want to look into using XML literals to build your HTML instead of StringBuilder. XML literals will make your code SUPREMELY more readable, and allow for very easy insertion of data into your message.
As a SIMPLE example...
Dim msg = <html><body>
Message sent at <%= Now.ToString() %>
</body></html>
myMailMessage.IsBodyHtml = True
myMailMessage.Body = msg.ToString()
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.