Currently I’m doing a project that uses Entity Framework Code First for data access. Though I’m not 100% convinced that this technology is mature enough, a coworker of mine recommended it. For the read side of our project we want flattened dto’s that are made to fit our view’s need. Since some of the views were a bit too complex to write with linq to entities we thought it would be best to write stored procedures for them.
The problem here is that Entity Framework Code First does not support Stored Procedures out of the box. Well… it actually does, but in such a way that it is indistinguishable from plain ADO.NET. Yet I wanted a more type safe solution. I’m still not sure if this is the best solution for this problem but I thought I would share the code with you.
Imagine we have a stored procedure:
DECLARE @Iets int
DECLARE @NogIets bit
SET @Iets = 5
SET @NogIets = 1
EXECUTE [dbo].[sp_TestProcedure]
@Iets
,@NogIets
GO
The standard way of calling the stored procedure in EF Code First would be something like this:
var ietsParameter = new SqlParameter("@Iets",5);
var nogIetsParameter = new SqlParameter("@NogIets",true);
DbContext.Database.SqlQuery<ProcedureResult>("sp_TestProcedure @Iets @Nogiets", ietsParameter, nogIetsParameter);
After creating the database extension you can write a more typesafe solution:
var testProcedureStoredProcedure = new TestProcedureStoredProcedure() { Iets = 5, NogIets = true };
var result = DbContext.Database.ExecuteStoredProcedure(testProcedureStoredProcedure);
The typed stored procedure looks like the following:
public class TestProcedureStoredProcedure : IStoredProcedure<ProcedureResult>
{ public int Iets { get; set; } public bool NogIets { get; set; } }
Notice that you have to inherit from a generic IStoredProcedure and supply the type of the result of the stored procedure. The stored procedure class contains properties that are used as the parameters for the execution of the stored procedure. The extension will use the name of the class to determine which stored procedure to execute. The default behavior is ‘sp_’+classname but you can edit the source to your own naming convention.
You can download the database extension class here, or get it from github. Just add a reference to the project and import the namespace to start using the extension method.
There is a drawback however. The execution time is slower because before it can call the query it has to reflect the properties of the stored procedure class. It’s still a work in progress but it can be undoubtedly be executed faster by adding some kind of cache for the stored procedure names into it. If you have any improvements then I would be happy to hear about them!
A small note: if you have any questions about my blog posts or if there are any links broken then please add a comment to the blog post in question. Mails often get lost in my mailbox and it can take a couple of weeks before I can answer them.
I've created a new
extensions project for Entity Framework Code First. You can read all about it here!
Thanks, this was perfect for my EF Code First approach and works great.
BeantwoordenVerwijderenYou're welcome, enjoy!
BeantwoordenVerwijderenDeze reactie is verwijderd door een blogbeheerder.
BeantwoordenVerwijderenAwesome.. This is exactly what i am looking for.. Thanks for helping me out .. You Rock
BeantwoordenVerwijderenThanks, if you have any improvements then be sure to submit the changes.
BeantwoordenVerwijderenwhat is procedureresult in this post pls let me know
BeantwoordenVerwijderenProcedureResult is the return value of a single record. If you for example have a query
BeantwoordenVerwijderen'SELECT Name, FirstName FROM dbo.Person'
then your ProcedureResult would be:
class MyStoredProcedureResult
{
public string Name {get;set;}
public string FirstName {get;set;}
}
The return value of your executed stored procedure will be of IEnumerable< ProcedureResult>
Accidently removed some comments, sorry if you're one of them -_-
BeantwoordenVerwijderenDon't name your stored procedures starting with "sp_".
BeantwoordenVerwijderenhttp://sqlserverpedia.com/blog/sql-server-bloggers/stored-procedure-performance-using-%E2%80%9Csp_%E2%80%9D-prefix-%E2%80%93-myth-or-fact/
VerwijderenOk, thx for the link. I wasn't aware of that.
VerwijderenIt's open source though so you can use whatever naming convention you'd like.
that's great thanks
BeantwoordenVerwijderenDbContext.Database.ExecuteStoredProcedure here i don't get the
BeantwoordenVerwijderenExecuteStoredProcedure
What is the ProcedureResult ?
please update the code related to calling stored procedure using Entity framework
Deze reactie is verwijderd door de auteur.
BeantwoordenVerwijderenHi,
BeantwoordenVerwijderenI have a custom class like
class MyStoredProcedureResult
{
public string Title {get;set;}
public string FirstName {get;set;}
Public List < Numbers > {get;set;}
}
Here Can I get the List Numbers from my SP?
or your sample can work on simple type of classes?
My table data is like below
Person Table
--------------
ID Title FirstName
1 Mr. James
2 Mr. Roger
Numbers Table
----------------
PersonId Number
1 98989898
1 99999999
1 14528965
2 14526398
2 14587956
So here how can I get the related data for my class.?
Just my two cents, I like your initial idea of the Database extension and the ability to generalize SP calls and also maintain type safety of the parameters. And I do intend to use it in my application. So for it, just a suggestion, adding annotations to the SP class to determine IN / OUT parameters would help while creating the sql parameter objects for use in the SP call as either input or output parameter.
BeantwoordenVerwijderenGood Code!