ASP.NET MVC Partial Model Binding from Stored Procedures - asp.net-mvc

Currently, I have a set of stored procedures which are called to populate different fields on a page. I am calling the stored procedures from the LINQ to SQL class that I dropped them on, which works fine. However, it automatically generates (StoredProcedureName)Result class names which I have to work with.
Is there anyway to take a stored procedure and bind the result to multiple classes? For example I have a stored procedure that gets the information for a blog post. I want to bind that data into a Post class and a User class (for the author), however I am not retrieving all of the data from the stored procedure to fill an entire Post object or User object (the stored procedure only returns the title, content, and author name).
What is the best way to handle this scenario? I am open to changing the stored procedure but I would rather not have to return data that I am not going to use just to populate a full object and I cannot use LINQ to SQL to query the database.

You can create a partial of your DataContext and write a method that returns IMultipleResults, binding to each of your respective classes with a [ResultType(typeof(ClassName))], as shown here:
http://msdn.microsoft.com/en-us/library/bb399371.aspx
Or, you can store the results of the stored procedure in a variable and then LINQ-Select new instances of your target classes like this:
var result = dataContext.your_stored_proc();
var post = result.Select(s => new Post { Id = result.Id, Title = result.Title });

You can use this library:
https://github.com/mrmmins/C-StoreProcedureModelBinding
This classes are using reflection, and you need include it in your project and create an instance of Generic.cs

Related

MVC Entity Framework calling stored procedure

I am using ASP.NET MVC 4.5 and EF. I import the stored procedures into my ADO.NET Entity Data Model. I have my .edmx and XX.tt with my StoreProcedure_Result.cs.
I use
var result = dbcontext.SP(Param).AsEnumerable().First();
My problem is that those stored procedures that have
select count(id) as Count from table
doesn't appear on my SP_Result.cs
Any ideas?
I just tried this out myself and did not see a "_Result.cs" class created either for the sproc that just returns count(). I'm guessing that a _Result.cs class does not need to be created because it is just a single int, and a specific type is not needed. I was still able to call the sproc though. You could obtain the int like this...
var result = db.getCount().First();
int i = (int)result;

Supplying the model with varying amounts of data from database

Supposed I have an online store and a model User, which contains a whole bunch of parameters (First Name, Last Name, an Address object, ProductCategoryAccess object etc.)
The way it's currently set up is the constructor accepts an Id and populates the entire class with data from the database.
But what if I don't need all that data? For example, if I have a view that just lists users, I'd have to create a list of Users, with each of them needlessly querying the database for information that I don't need (Address, ProductCategoryAccess, etc).
What's the best way of handling this? Do I create a bunch of different classes, with only the parameters I need for various situations? Do I create one User class, but with different "setter" methods, which will use different queries to populate only certain parameters?
Are you using any ORM tools to get the data? If yes, then you could use lazy binding to retrieve only elements that you need.
If you are directly querying the db, then dividing it across different methods with queries should do the trick.
What are the different situations you need to account for?
If you only wish to select certain properties from your user database record then you can use projections to bind the records into a data transfer object that contains only the properties you need for any given page.
For instance, if you needed properties for an edit user page then your query (I assume you're using Entity Framework?) would look something like this:
this.userContext.Users.Where(y => y.UserId == userId).Select(x => new UserEditDto {
FirstName = x.FirstName,
Surname = x.Surname,
EmailAddress = x.EmailAddress
}).FirstOrDefault();
What this will do is build a LINQ query against the database that selects only the properties specified within the select part of the LINQ statements. In fact, if you were to remove the FirstOfDefault() method and stick a breakpoint in you'd be able to see the SQL generated by that statement would look a little something like:
SELECT FirstName, Surname, EmailAddress FROM users WHERE userId = 1;
It's only when you call .FirstOrDefault() does the LINQ provider execute the query against the database and return the result.
From here you're able to return your DTO to your service layer or your controller to send it to a view within a view model. You can then rinse and repeat this same type of query for other possible data transfer objects and views that require certain data.

how to get the default values from the model into a new breeze clientside entity

i would like to create new entities which use the default values defined in the model.
i've checked the retrieved metadata, and the default values are there:
{"name":"LastName","type":"Edm.String","maxLength":"50","unicode":"true","fixedLength":"false","defaultValue":"admin:
Nachname"},
however they are not taken into consideration when creating a new entity.
This is a bug in Breeze that should be fixed in the next release, out in about week. When this fix gets in then breeze will honor any defaultValues it finds in the EntityFramework data model.
One problem though is while it is easy to get 'defaultValues' into a Model First Entity Framework model via the properties editor, it's actually difficult to get it into a Code First EF model, unless you use fluent configuration. Unfortunately, EF ignores the [DefaultValue] attribute when constructing Code First model metadata.
One workaround that you can use now is to poke the 'defaultValue' directly onto any dataProperty. Something like:
var customerType = myEntityManager.metadataStore.getEntityType("Customer");
var fooProperty = customerType.getProperty("foo");
fooProperty.defaultValue = 123;

Stored procedure not appearing in EF code

I'm using EF database first and have added a stored procedure to the database.
When I ran Update model from database on the edmx file it picked up the stored procedure and I selected it as an item I wanted to include.
I have a file named Model<projectname>.Context.cs with a class called Entities in it. This is an auto-generated class and it contains methods for other stored procedures in the system. My new stored procedure does not have a corresponding method in this class and running Run custom tool does not help.
Is there something else that I need to do, that I am not doing?
Thanks,
Sachin
EDMX doesn't support Table-valued parameter. So if your proc uses the TVP as the parameter, the EDMX designer can't pick it up.
Edited:
If you want to retrieve the result set and create object/POCO for the proc, then just simply remove the tvp, compile the proc, let the EDMX designer to pick up your proc, generate the result object and then add the tvp back to your proc. This is a very easy way to cheat the EDMX designer and get what you need.
Ensure you are doing "Run Custom Tool" on the *Model.CONTEXT.tt file.

Storing complex types in Entity Framework

I have created a database using the edmx designer in an ASP.NET MVC project. This has a number of tables like this:
An Office can have many Locations
Each Location can have many Staff
Each Location has Location Type
Each Location has a Business Type
Each Location has a Browser Version
Each Browser Version has a Browser
The details of this are probably unimportant. The core class is Staff, it has a Location property, which has an Office property, a LocationType property, a BusinessType property and a Browser Version property (which has the Browser property).
I'm creating a registration form. I started by trying to create a Staff member instance to save by using code like staffMember.Location.LocationType = DB.Locations(l => l.Id = model.Id);
which populated the class with fully populated class instances. Calling the save method at this point would blow up with :
Entities in 'DBContainer.BrowserVersions' participate in the
'BrowserBrowserVersion' relationship. 0 related 'Browsers' were found.
1 'Browsers' is expected.
Now, again, the BrowserVersion.Browser class was correctly populated.
So, I did some reading, and as a result I made sure my code always uses the same DBContext. This did not fix my issue. So I changed my code to do something like this:
staffMember.Location.BrowserType = new BrowserType { Id = myBrowserType.Id };
This would then blow up with an error like :
{"Cannot insert the value NULL into column 'BrowserName', table
'MyProject.dbo.Browsers'; column does not allow nulls. INSERT
fails.\r\nThe statement has been terminated."}
In the end I found I cannot use the objects copied from my DBContext, but I need to create objects that have all the relevant properties copied across from the objects I get from the DB. Surely I am doing something wrong, I'm writing more code now than if I used stored procs and my own data layer?

Resources