I\'ve asked a few questions on this topic before. Before we\'re able to implement either MVC or LINQ at work we need to resolve a few issues.
Multiple Recor
Multiple Record Sets in ASP.NET MVC:
If you have stored procedure that return A and B. Then you create a specific ViewModel:
public class AB
{
public A DataA { get; set; };
public B DataB { get; set; };
}
You can also use the ViewData dictionary instead of the Model property (or in combination with this property which also works)
Strongly Typed Stored Procedure Output
You create a specific class for the results returning from the stored procedure with custom fields.
LINQ Column Lookups
Not 100% sure about this, but LINQ lookups the column field names and parameter names from a stored procedure at design time.
Yep - most definately.
First u need to manually create a method that calls the stored proc, returning an IMultipleResults
result.
This blog posts has all the info u need. It's simple to do and very easy and works.
What you need to do is two steps.
eg.
IndexViewData.cs
public class IndexViewData
{
IList<Customers> Customers { get; set; }
IList<Products> Products { get; set; }
}
.
HomeController.cs
public ActionResult Index()
{
IList<Customers> customers;
IList<Products> products;
// This grabs the multiple records from a single stored procedure.
// This code taken from the blog post link, above.
using (NorthwindDataContext db = new NorthwindDatacontext)
{
IMultipleResults results = db.GetMultipleRecordSets(arg1, ....);
customers = results.GetResult<Customer>();
products = results.GetProducts<Product>();
}
// Now return the view, with the viewdata that is required.
return View(new IndexViewData
{
Customers = customers,
Products = products
});
}
.
Index.aspx
<%@ Page
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IndexViewData>" %>
<% Html.RenderPartial("CustomersUserControl",
ViewData.Model.Customers); %>
<br/>
<h2>Products</h2>
<% foreach(var product in ViewData.Model.Products) { %>
Name: <%= product.Name %><br/>
<% } %>
...
Please note, i have not done any error checking, etc. it's a really quick pseduo code guide to getting u started.
Note #2: Please take note that the Index view is strongly typed (it inherits the ViewPage.
I've answered this, above. Please note, u can strongly type your ISingleResult stored procedures.
Ok, i think i understand what you mean, here.
When you create your method, which calls the stored procedure (either an ISingleResult
or an IMultipleResult
) you are defining the paramters that are required, there and then ... think of it as being hard-coded.
When you drag-n-drop tables onto the linq to sql context gui canvas, Visual Studio does a lookup check there and then. It then creates the classes in one of the various files for the context. eg. NorthwindDataContext.designer, etc. So, it's a one-hit-job. Once the class is created, the designer then displays this on the canvas. There is NO SYNC back to the database. None. Nada. Zilch. If you change anything in your database schema (eg. add a new field, change a stored procedure argument, etc) the datacontext will NOT know about it. You need to delete the table and drag-n-drop it back.
If you have SQL Profiler running while you drag-n-drop a table or stored procedure onto the canvas, you can see Visual Studio 'querying' the database for the information. :)
So yeah. It's fire-n-forget. A one-hit-job. Required manual sync.
HTH.
I noticed u added two more q's, so i'll add my answers, under here.
This is a personal decision. 15 DB's! shees! that's a fair number. Anyways, it comes down to how maintainable your Context canvas becomes. Secondly, every context creates it's OWN database connection. So if your method decides to call 4 contexts, then you've got 4 connections (and round trips) to the db, dude :)
Personally, I have all my tables on the Context Canvas. I never use those table classes in my code. They are private and only used in my Repository namespace/project/dll. I THEN use POCO classes to move all my stuff around. This keeps my code, cleaner and not dependant on the repository.
If you've dragged the stored proc onto the linq context canvas, please delete it. There needs to be no references to the method UserDetails(int userId)
.
Now, add the following code (you'll need to convert it to VB.NET) to the data context's partial class (i'm assuming u know what that is/means, btw) :-
[Function("UserDetails")] // <-- This is the name of your stored procedure.
[ResultType(TypeOf(UserDetail))]
[ResultType(TypeOf(Office))]
[ResultType(TypeOf(ActiveUser))]
[ResultType(TypeOf(Department))]
public IMultipleResults UserDetails(
[Parameter(Name = "UserId", DbType = "Int")] int userId)
// /\____ /\_____ ____/\
// This is where u _define_ the stored proc arguments.
{
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)MethodInfo.GetCurrentMethod())), userId);
// This is where all the stored proc arguments are set ____/\
// This can be multiple args. eg. userId, name, ...
return (IMultipleResults)result.ReturnValue;
}
then use it like u did in your previous VB.NET code.
The problem (i'm guessing) was that you haven't made the method to handle IMultipleResults
. You're still using the old stored proc code-signature, which was made (by default) to only be a single recordset result (ie. ISingleResult
).
This is the default if u drag-n-drop a stored from from the Server Explorer onto the linq Context Canvas.