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.
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 am trying my hands on MVC 2, ADO.NET EF and POCO. I have generated my entity classes in a separate library using POCO generator.These POCO entities are used as ViewPages (Not sure if that's the right way to design or do I need separate ViewModels classes ?)
Now, if I take case of a simple scenario where I need to add an Employee object( which is related to a Department Master), what then should be the recommended way to transfer these objects between layers.
Layered structure of the application is somewhat like this :
I have thought of various alternatives:
I have a method in the Employee Controller which is named AddEmployee() which accepts the FormCollection as parameter. Within the form collection I get posted data such as Employee Name, Age , Salary etc and the ID of the Selected Department .
1.) One way is that I can create another DTO say EmployeeDepartment DTO which will be used to map values from FormCollection as is. I can then break them at manager layer and use them to create entity objects i.e Employee Object and refer department by query similar to this:
e.Department = Department.where(i => i.deptId == empDepDto.dept_id).first()
I am not a big fan of this and feel that every time there is a relation involved I have to add a DTO and then map it to my entity class.
2.) Second is probably the worst, i.e passing each object as parameter and then couple them in manager layer.
3.) Use POCO as is, Create a Employee Object and Deparment Object at controller layer and pass the POCO object
public void AddEmployee(FormCollection formCollection)
{
Department d = new Deparmtent; d.id = ""; //based on the dropdown value
d.name="" //based on the dropdown selected text;
Employee e = new Employee; e.Name. e. sal....
e.Department = d;
EmployeeManager.AddEmployee(e);
}
But at manager layer I think , I still need to recreate the reference to the Department using LINQ which again is repetitive and doesn't seems to be a clean solution.
Are there better ways of handling this ? Looking for recommendations and best practices.
Firstly, is there any reason you're not using MVC version 3? There's no major breaking changes, so may as well upgrade?
Secondly is there a reason for using FormCollection rather than the strongly typed model-binding? Just change your views to use the strongly typed HTML helpers ( like <%: Html.TextBoxFor(m => m.Property) %>), or make sure the name attributes match the property names, and have your controller receive the type, and model binding will do the rest. There's plenty of tutorials showing this, and articles explaining it. Model binding will work with a name/value collection, like that posted as a form, or against JSON data, or you can find/write custom model binders that work against whatever wacky serialisation protocol you want.
One thing to watch though when passing the actual entity types that Entity Framework will store around, is that you have to be careful when updating existing objects, or with foreign key references to existing objects - all your objects must be attached to the right Entity Framework context. To achieve that you will often see the objects received by the controller having their properties copied to a freshly retrieved entity from a context, either manually or by an object mapper of some kind.
Make a seperate project called "BusinessObjects" or "Model" which contains your POCOs. Then use strongly typed model-binding for MVC and you'll be set.
The method signature will look something like this:
// In your Controller
public void AddEmployee(Employee newObject)
{
YourDataContext dc = new YourDataContext();
dc.Employees.Add(newObject);
dc.SaveChanges();
}
Today is my first day using ASP.NET MVC, and I'm finding it very intriguing. I only just started learning asp.net.
So basically I'm trying to call a procedure from an MSSQL database, and with it I need to send a paramater "PlaceID", which is an integer. This procedure basically just picks out a number of columns from different tables in the database. Here is the Linq to SQL code
The ultimate goal is to be able to retrieve all the information and return it as JSON with a function that will be available for a javascript.
I'm wondering what is the best way to proceed from here. I know I have to create a view, but I'm still unclear exactly on how I can call the procedure and make it store all the information. I could really use some help on this, some code examples would be excellent. I already wrote a C#.net function to convert a datatable to JSON using a stringbuilder, but I get the feeling there is a smarter way to do things.
Any help is very appreciated.
Might I suggest going through the NerdDinner.com example first. I really think that you may have started down the wrong road and it would be worth backing up and doing some review first. For one thing, you probably don't want to be mixing DataTables and LINQ, typically you'd work with strongly-typed models and have your data context/repository return IQueryable/IEnumerables of the model instead of a DataTable. For another, there is a controller method that is able to turn a model into JSON for you. Generally, you should need to write your own JSON serialization.
Declare a list and serialze it into json.
Here Lstcustomeris a genric list of class type customer
I Assign values to class varable and then insert this class in list of Lstcustomer
e.g.
Dim js As New System.Web.Script.Serialization.JavaScriptSerializer
Return js.Serialize(Lstcustomer)
I'm trying to write some code using pure SQL using ASP.NET MVC.
I assume I should be building a model, and sticking to the MVC pattern.
Any suggestions for good practice would be highly appreciated, and examples very useful too. For example I'm not sure if I should be splitting this code off from my main repository's, and if I should, where should I put it?
Also I will be attempting to return data from 2 tables in this query.
The kind of query I would like to use is like this.
See top answer from this page
How to implement high performance tree view in SQL Server 2005
Also
string sqlGetQuestionAnswers = "SELECT TOP (10) * FROM tblquestion ORDER BY NEWID()";//
using (SqlDataAdapter dapQuestions = new SqlDataAdapter(sqlGetQuestionAnswers, ConfigurationManager.ConnectionStrings["SiteConnectionString"].ToString()))
{
DataSet dsQuestions = new DataSet();
dapQuestions.Fill(dsQuestions);
if (dsQuestions.Tables[0].Rows.Count > 0)
{
work with data;
}
else
{
Error;
}
}
Given you want a SQL to MODEL approach this might work for you.
I'm using a LinqToSQL data context here;
I have a table of Articles that contains let's say 10 fields but all I want is the title so I create a class;
public class Art
{
string title { get; set; }
}
Then I have my data context object
static ArticlesDataContext dc = new
ArticlesDataContext(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
Then I can fill my, albeit simple, model;
var arts = dc.ExecuteQuery<Art>(#"Select * from articles");
Does this help or am I off base?
Leave it in your repository. The purpose of a repository is to abstract away your domain operations - if every function uses a different datasource and different methods of accessing the data (sql, file IO, http), so be it - the repository's clients won't know the difference.
Obviously the more cohesive you make the repository though, the easier it will be to maintain. However, this code definitely belongs there.
This seems like the "bloody knuckle" approach - you're really not using any of the 3.5 features that solve problems like this on your behalf.
That said, I would suggest that you build business objects in your model folder, and let your business objects handle their persistence using your SQL. Don't put the SQL in your controller, and definitely not in your view. Maintain a clear separation between these layers, and your life will be much easier.
I am using web forms, C#, Asp.net.
As we all know, in this model UI and business logic are often mixed in. How do I separate these effectively?
The example I would like to use is:
I have a GridView and a DataTable (GridView binds to the DataTable and DataTable is fed from the stored procedure).
I would like the GridView (UI) and DataTable (business logic) to be decoupled.
Is it worth it to write an wrapper for DataTable? Are there practical patterns that have been proved and tested that you could recommend to be followed?
If someone with experience could shed some light, that would be awesome.
And, as a final note I would like to say that ASP MVC is not an option right now, so don't recommend it.
My database access layer returns a DataTable.
Note that I HAVE to use this database layer as this is a company policy.
I went through this recently while decoupling much the same thing from our UI layer.
You can see my progress here and here.
In my opinion, A DataTable does not represent business logic. Specifically, it's data pulled directly from the database. Business logic turns that data into a truly useful business object.
The first step, then, is to decouple the DataTable from the Business object.
You can do that by creating objects and List<object> that make up DataTables and Collections of DataTables, and then you can make a ListView that displays those Objects. I cover the latter steps in the links I posted above. And the former steps are as easy as the following:
Create a class that will represent your object.
iterate through your DataTable (or DataSet, or however you retrieve the data) and shove those fields into properties of that object (or that List<T>);
return that List to the Gridview or ListView to display.
This way your ListView or Gridview won't be tightly coupled to the method that you are retrieving your data. What happens if you decide to get your data from a JSON query or a XML file later on? Then you'd have to build this into there.
Step 1 - Getting Data From Database
There are multiple methods to get data from a database, there's no way I can go through all of them here. I assume that you already know how to retrieve data from a database, and if you don't, there are quite a few links to follow. Let's pretend you've connected to the database, and are using an SQLDataReader to retrieve data. We'll pick up there.
Class Diagram
Foo
----
id
Name
Description
And here's the method:
private void FillDefault(SqlDataReader reader, Foos foo)
{
try
{
foo.id = Convert.ToInt32(reader[Foo.Properties.ID]);
foo.Name = reader[Foo.Properties.NAME].ToString();
if (!string.IsNullOrEmpty(
reader[Foo.Properties.DESCRIPTION].ToString()))
foo.Description =
reader[Foo.Properties.DESCRIPTION].ToString();
else foo.Description = string.Empty;
}
catch (Exception ex)
{
throw new Exception(
string.Format("Invalid Query.
Column '{0}' does not exist in SqlDataReader.",
ex.Message));
}
}
Once that happens, you can return a list by going through that process in a while loop that targets the SQLDataReader.Read() function.
Once you do that, let's pretend that your Foo being returned is a List. If you do that, and follow the first link I gave above, you can replace Dictionary<TKey, TValue> with List<T> and achieve the same result (with minor differences). The Properties class just contains the column names in the database, so you have one place to change them (in case you were wondering).
DataTable - Update Based on Comment
You can always insert an intermediate object. In this instance, I'd insert a Business Layer between the DataTable and the UI, and I've discussed what I'd do above. But a DataTable is not a business object; it is a visual representation of a database. You can't transport that to the UI layer and call it de-coupled. They say you have to use a DataTable, do they say that you have to transport that DataTable to the UI? I can't imagine they would. If you do, then you'll never be de-coupled. You'll always need an intermediate object in between the DataTable and the UI layer.
I'd start by decoupling the data table right into the trash can. Build a domain layer, and then some type of data access layer which deals with the DB (ORM recommended).
Then build a servicing layer which provides the data to the UI. All business logic should be within the service or the entities themself.
Consider implementing MVP (model view presenter) pattern. It gives you separation of biz logic through presenter interface, which also allow better unit testing capabilities. Your codebehind of aspx page is then just connector of events and getter/setter of properties. You can find it in MS pattern&practices enterprise application blocks (CAB - composite application block - if i'm not mistaking).
You can read more about it here: http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
But also going from DataTable/DataSets to objects (POCO) is preferred.