Note: Some of the features tracked in this issue could help with using EF Core with database views. However, the feature is not limited to database views and its completion would not mean that every aspect of database view support has been implemented. See #827 for an overview of the areas where EF Core interacts with database views.
(added by @divega on Sep 4, 2014)
This is a general meta-issue for enabling better support for working with stored procedures in EF Core, with an emphasis on mapping stored procedures to parts of the EF Core model as opposed to using them in an ad hoc manner, which is covered in other issues. There are different aspects of stored procedures support than should be consider separately, e.g.:
FromSql
)Note that for data retrieval stored procedures aren't generally considered composable on the store i.e. it wouldn't normally be possible to reference them in LINQ queries without causing all the further processing to switch to the client (#621 and #622 cover composable functions) but with our compensating LINQ provider it could be possible some day to enable mapping specific LINQ patterns to stored procedures calls, e.g.:
C#
var customerOrders = db.Orders.Where(o => o.Customer == customerId);
Could cause a stored procedure OrdersByCustomerId(int @customerId)
to be invoked.
IMHO one of the most useful features of EF 6 is wrapping stored procedure into DbContext-based class methods. So it would be better to include such feature in EF 7 and if it's possible make two improvemtnts:
1). make available EF to generate methods with out-parameters for OUTPUT SQL keyword (and also ref);
2). make EF available to generate async/await verson of such methods.
Also a good idea would be to add User Defined Table Type support for Stored Procedure parameters when generating the DbContext-based class methods using the edmx Database first code generator.
Note: Support for stored procedures with client composition on DbSet<T>
was added via #1864
Where I can find any example of using stored procedures with client composition on DbSet
There are a few examples in the functional tests FromSqlSprocQueryTestBase.cs.
The general pattern is to call the FromSql
extension with the stored procedure command text and compose on the result:
myContext.Products.FromSql("[dbo].[Ten Most Expensive Products]").Where(...
or command text format string and parameters:
myContext.CustomerOrders.FromSql("[dbo].[CustOrderHist] @CustomerID = {0}", "ALFKI").Where(...
This feature depends on the generic type of the DbSet
being a type that can be populated from the columns returned by the stored procedure. There are still some limitations/issues when the composed methods require server side execution (i.e. Include
or additional FromSql
calls #2420), and there is no support for saving changes to the results at this time.
Code with FromSql is outside of the context class (myContext), am I right?
Are there any plans to support stored procedure mapping in RC?
@Aristarh71 FromSql uses your context, and you can always hide it away in a method on your context:
``` c#
public class BloggingContext : DbContext
{
public DbSet
public IEnumerable<Blog> FindBlogs(string searchTerm)
{
return this.Blogs.FromSql("SELECT * FROM dbo.SearchBlogs(@p0)", searchTerm);
}
}
```
Are there any plans yet to provide a way to consume stored procedures without having to set up a real entity type in the model builder? So that we only get the mapping capabilities, but leave out redundant stuff like the whole change tracker? I already add a AsNoTracking()
after everything, but the structures are still there even if it doesnât make sense for the types.
So ideally, I would just like to be able to define âmapping entitiesâ (I have no idea how these are actually called), that donât do anything except provide the definitions when EF needs to map a result onto that type. This would then also mean that normal entity restrictions would not be necessary (e.g. having no primary keyâwhich is perfectly reasonable for non-tracked items from a stored procedure).
@poke I think that is an interesting idea... it's probably also something you want when you map views (or at lease non-updateable views). We'll keep that in mind when we come to these features.
RE: mapping capabilities/non-updateable views
This would be a great feature, just map to a type, key or no key
In our case we want to hide the keys sometimes for a read-only view of the result
+1 for OUTPUT support.
As for a real world example: When doing paging using stored procedures, we need to run 2 queries. One to get the paged entities and another to get the total row count of unpaged entities to build a pager. By passing an OUTPUT
parameter, we could reduce this to a single query. We can use both OFFSET
and COUNT() OVER
in a single query and return both (entities and total # of rows thru the OUTPUT
parameter).
This is just one example. I'm sure many will benefit this if implemented.
@dealdiane I would recommend filing a separate bug if your main interest is to have output parameters supported in FromSql()
queries. Otherwise I am afraid your request is going to be lost in a comment in this bug that is already in the backlog. It would also be great if you could include the actual SQL (I assume it would be a stored procedure) to illustrate your particular scenario better.
+1 for adding Stored Proc Async/Await Support
-1 for out/ref parameters because it would conflict with adding async support.
I reverse-enginered an existing SQL Server database and added the model classes and context class to my MVC 6 project. This is my controller constructor, I assume DI will take care of injecting the context (which is registered as a service in StartUp.cs)
public ReportsController(akzent_reportsContext context)
{
this._context = context;
}
Now on a controller method I'm trying this:
IEnumerable
But I get this compilation error:
'akzent_reportsContext' does not contain a definition for 'FromSql' and no extension method 'FromSql' accepting a first argument of type 'akzent_reportsContext' could be found (are you missing a using directive or an assembly reference?) Reportes.DNX 4.5.1, Reportes.DNX Core 5.0
I've already added the EntityFramework.Relational 7.0.0-rc1-final package to the project, and in the controller I am
using Microsoft.Data.Entity;
What am I missing?
Thanks for any insight.
FromSql
does not exist on the database context but on a contextâs DbSet
. For example as shown in the code above: context.Blogs.FromSql(âŠ)
.
The reason for this is that EF does need to know the resulting entity type it should materialize from the SQL statement. This also means that youâcurrentlyâneed to declare entities for your stored procedure result.
a
Does anyone know where I can find source code project to download the uses the FromSQl to call a stored procedure that actually compiles and works,
As explained above, you can just call FromSql
on the DbSet
to materialize a result of registered entities. If you are having problems with that, feel free to open a question on Stack Overflow to ask for help with your specific problem (but remember to include a MCVE).
Otherwise, this issue is used to track the progress for stored procedure progress, so itâs not really the right place to ask for individual usage assistance.
I am using EF Core in a windows class library and not a web class library.
I do not see the FromSQL extension on the entity class referenced by the derived dbcontext
object.
I guess I have to see what other assembly I need to install..
I am looking to call a StroredProcedure not an sql statement. Is there a working code example available for download that show FromSql calling a stored procedure?
See the functional stored procedure tests on how to consume stored procedures. As I already said, you need to run it _on a DbSet
_, not on the context or some entity type. And there is no way to call stored procedures other than to execute SQL right now.
I did not say run it from the DBContext. At least I did think I said that.
I said reference to the entity referenced by the DBContext such as
dbContext.entity.FromSQL
The reason I could not find the FromSQL ion the entity was because an extension in an assembly was not loaded.
I used Net.Reflector to search through the various entity framework DLLs used in a Web Application and found the assembly that needed to be load..
@rowanmiller I read several issues here, but I'm still not sure what's the current status of SP support and how things should be done.
Is there a place that summarize what's supported and what's not?
And how to do do each action.
@gdoron the only thing that is supported at the moment is using DbSet.FromSql
to run raw SQL to return results from a stored procedure. Proper stored procedure support will not be in the 1.0.0 release. See the roadmap for more info.
@rowanmiller And what about the most common scenario (at least from my experience), that the SP doesn't return an exact table row but adds some of other tables?
E.g.
Customers:
Id,
Name,
Orders:
OrderId,
CustomerId,
Price
And there's a SP that returns something like this:
select Sum(O.Price), C.Name
from Customers C
inner join Orders O
ON O.CustomerId = C.CustomerId
where C.CustomerId = @customerId
Do I need to create a fake Entity and ignore it in the Migrations like with VIEWs?
Fallback to DataReader (Yuck!)
Thanks
@gdoron yep there is no nice way to handle that right now. What is available is really just a workaround for the lack of proper stored procedure support in EF Core.
We totally get that this is a massive limitation for an O/RM, just reiterating what the roadmap says about the list of missing features that stored procedure support is part of:
The things we think we need before we say EF Core is the recommended version of EF. Until we implement these features EF Core will be a valid option for many applications, especially on platforms such as UWP and .NET Core where EF6.x does not work, but for many applications the lack of these features will make EF6.x a better option.
I'm trying to call stored procedure in my dbcontext class using the entity type. Please find the code below:
public IEnumerable
{
DateTime startdate = new DateTime(2017, 03, 15);
string sdate = String.Format("{0:MM/dd/yyyy}", startdate);
DateTime enddate = new DateTime(2017, 03, 01);
string edate = String.Format("{0:MM/dd/yyyy}", enddate);
var storecheckData= StoreCheckByDate.FromSql("exec dbo.StoreCheckByDate @StartDate={0},@EndDate={1}", sdate, edate);
return storecheckData;
}
On executing, i'm getting the following error:
Using async/await i modified the stored procedure call.
Controller class
```C#
[HttpGet]
public async Task
{
return View(await _totalSalesRepository.GetStoreCheckData(););
}
Repository class
```C#
public async Task<IEnumerable<StoreCheckByDate>> GetStoreCheckData()
{
return await _totalSalesContext.ExecuteStoreCheckQuery();
}
Dbcontext
```C#
public async Task
{
DateTime startdate = new DateTime(2017, 03, 15);
string sdate = String.Format("{0:MM/dd/yyyy}", startdate);
DateTime enddate = new DateTime(2017, 03, 01);
string edate = String.Format("{0:MM/dd/yyyy}", enddate);
return await StoreCheckByDate.FromSql("exec dbo.StoreCheckByDate @StartDate={0},@EndDate={1}", sdate, edate).ToListAsync();
}
Model Class
```C#
public class StoreCheckByDate
{
[Key]
public DateTime Date { get; set; }
public string UserCode { get; set; }
public string SalesmanName { get; set; }
public string Role { get; set; }
public string ClientCode { get; set; }
public int TotalApplicableCount { get; set; }
}
Stored Procedure
CREATE proc [dbo].[StoreCheckByDate]--SalesByBrand '02-01-2017','02-28-2017'
@StartDate DATETIME,
@EndDate DATETIME
AS
select date,usercode,salesmanname,role,clientcode,totalapplicablecount from tblStoreCheck
where date<= @StartDate and date> @EndDate
order by date
I'm getting following error:
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
lambda_method
Stack Query Cookies Headers
NullReferenceException: Object reference not set to an instance of an object.
lambda_method
Shape
<_ShapedQuery>b__0
MoveNext
ThrowForNonSuccess
HandleNonSuccessAndDebuggerNotification
MoveNext
ThrowForNonSuccess
HandleNonSuccessAndDebuggerNotification
MoveNext
Any help would be highly appreciated!!
@maclax Can you open a new issue for this? Please make sure to include the full stack trace for the exception you are seeing.
Hi, am new to EF Core (1.1). currently my app is in EF and is using lot of stored procedures. these stored procedures return a complex resultset meaning they don't directly map to a table entity in DB.
Can you point me to some examples where the SP returns a custom resultset which is not same as DB entity.
i have few other questions related to this.
Thanks in advance for the help.
@rajeshj18 As far as I know this is not yet supported. See this comment.
@rmarskell thanks for the reply. just to confirm, "_EF core 1.1 does not support calling sps which return resultsets which are different from db entities_". is that correct statement?
in above discussion is @maclax not trying to do the same thing?
can you shed some light on #1 and #2 questions above?
Thanks.
@rajeshj18 @rmarskell Please read this issue. As I repeatedly explained above, consuming stored procedures is possible with EF Core but requires you to set up the entity type (not a DbSet
). This is the case because EF can only materialize entities that are defined in the database context (using the model builder).
Iâve written an answer on Stack Overflow that shows how this exactly works. If that does not help, please open a question on Stack Overflow with your concrete issue. Feel free to ping me about it, and Iâll gladly help out since Iâve gathered a lot of experience with consuming stored procedures using EF Core. So yes, it is absolutely possible with a current version, just a bit annoying.
But please, stop polluting this issue with individual issues that are not about the actual progress on getting proper stored procedure support into EF Core.
@poke How little code is required in ModelCreating method, it looks a bit unclear from your SO reply
@ErikEJ You would set it up like any other entity that exists as a table in the databaseâexcept that it has no table, so you donât need to care about things like table name or index configurations. You can set up the entity either using the FluentAPI inside the model builder, or use the data annotations. This is explained in the modeling section of the documentation.
Itâs really just the same for an entity you would want to use for a stored procedure. In fact, if your stored procedure returns a result that can be mapped to an actually existing entity that also exists as a table, then you can just use that entity type and you donât have to do anything special for the stored procedure.
The FromSql
call does not care whether the entity it uses is actually useful and exists as a table or not. It does not even care if itâs a good fit for the result. It just requires that that entity is set up in the database context (so the context knows how to materialize it), and then it will use it to map the result to it.
So, to answer your question, the simplest model builder call might look like this:
```c#
modelBuilder.Entity
This will use either the data annotations or the normal conventions to set up the entity according to the properties that exist in the `StoredProcRow` type.
But you can also go the explicit route without data annotations and declare everything inside the builder:
```c#
modelBuilder.Entity<StoredProcRow>(entity => {
// entities are required to have a key, even if they donât matter for stored procedures
entity.HasKey(item => item.Id);
// but itâs a good idea to disable auto generating ids
entity.Property(item => item.Id).ValueGeneratedNever();
// these will use the normal conventions for the properties
entity.Property(item => item.Name);
entity.Property(item => item.Description);
// you can also map to different column names
entity.Property(item => item.DisplayName).HasColumnName("Title");
// you might even want to ignore some properties
entity.Property(item => item.Type).Ignore();
});
So this is all just the same as you would expect for a normal entity. If you would expose a DbSet<StoredProcRow>
from your context, you could now use this to access an actual table for this, but usually, there isnât one for stored procedure results. So you would just use a Set<StoredProcRow>()
internally to access the FromSql
method to execute the stored procedure and map the result to your type. Thatâs what I already showed in the SO answer:
c#
public virtual IQueryable<StoredProcRow> GetLoanDetails()
{
return Set<StoredProcRow>().FromSql("[sp_GetLoanDetails]").AsNoTracking();
}
A general note: Since youâre creating those stored procedure entity as normal entities, and since there is literally no difference to ânormalâ entities in your context, they will appear in migrations. There is currently no way to avoid this (as per #3436 and this issue), so you need to manually remove those from the generated migrations if you want to avoid creating tables for your âvirtualâ entities.
@rajeshj18 I have handled the same scenario.
Please find the below code:
public DbSet<SalesDataModel> SalesDataModel { get; set; }
var salesDataQuery = await SalesDataModel.FromSql("exec REPORTFORWEB_SALES @StartDate, @EndData, @Division, @Supplier, @ITEMCODE, @ITEMDESCRIPTION, @CLIENTCODE, @CLIENTNAME, @CLIENTBRANCHCODE, @CLIENTBRANCHNAME, @BRANDCODE, @BRANDNAME, @USERCODE, @USERNAME, @SUBCHANNEL",
new SqlParameter("@StartDate", startDate),
new SqlParameter("@EndData", endDate),
new SqlParameter("@Division", Division == null ? (object)DBNull.Value : Division),
new SqlParameter("@Supplier", SupplierName == null ? (object)DBNull.Value : SupplierName),
new SqlParameter("@ITEMCODE", DBNull.Value),
new SqlParameter("@ITEMDESCRIPTION", SKU == null ? (object)DBNull.Value : SKU),
new SqlParameter("@CLIENTCODE", DBNull.Value),
new SqlParameter("@CLIENTNAME", Customer == null ? (object)DBNull.Value : Customer),
new SqlParameter("@CLIENTBRANCHCODE", DBNull.Value),
new SqlParameter("@CLIENTBRANCHNAME", DBNull.Value),
new SqlParameter("@BRANDCODE", DBNull.Value),
new SqlParameter("@BRANDNAME", BrandName == null ? (object)DBNull.Value : BrandName),
new SqlParameter("@USERCODE", DBNull.Value),
new SqlParameter("@USERNAME", Salesman == null ? (object)DBNull.Value : Salesman),
new SqlParameter("@SUBCHANNEL", Channel==null?(object)DBNull.Value:Channel)).ToListAsync();
Here in the SalesDataModel, I define all the attributes that map to the parameters of the stored procedure.
How can i get output parameter value? The output value is always null.
SP parameter
@todoCounts VARCHAR(MAX) OUTPUT
```
works with `_context.Database.ExecuteSqlCommand(...)` but not with `_context.Set<T>().FromSql(...)`
```javascript
IQueryable<T> = _context.Set<T>().FromSql("Sp_Todo @todoCounts OUTPUT", // i also tried with OUT or without both Out/Output but no luck
new SqlParameter("@todoCounts", SqlDbType.Varchar)
{ Direction = ParameterDirection.Output});
I think that output parameters are only available once the query has been actually executed and the underlying reader is closed.
So, have you tried to materialize the queryable (call ToList
) and then inspect the output parameter?
@BladeWise I did call something like this,
var total=_context.Set<T>().FromSql("Sp_Todo @todoCounts OUTPUT",
new SqlParameter("@todoCounts", SqlDbType.VarChar)
{ Direction = ParameterDirection.Output}).ToList() // no luck
If i add this too, It works.
_context.Database.ExecuteSqlCommand("Sp_Todo @todoCounts OUTPUT",
new SqlParameter("@todoCounts", SqlDbType.VarChar)
{ Direction = ParameterDirection.Output}); // works
Am i doing something wrong here? Why isn't working the first statement? Thanks
I can confirm that this does not appear to work with FromSql
. Maybe you want to create a new issue for that @irowbin?
I made a blog post on something I did as a workaround until this is completely supported:
http://sinclairinat0r.com/2017/05/06/entity-framework-core--mapping-stored-procedures,-fluently
Christmas nuget for people who are still struggling with stored procedures : https://www.nuget.org/packages/StoredProcedureEFCore/0.1.0
thank you @verdie-g!
this is a very big present! I'm actually using it with mariadb database and it works!!!
I'm waiting for async methods
@briziomusic I'm glad it helped you
I've extended IDataReader which doesn't support ReadAsync and NextResultAsync methods. I should have extended DbDataReader. I will replace IDataReader with DbDataReader in the next realease, which will break the API :/
I also have to find a way to mock completely a DbDataReader for testing purposes.
@verdie-g amazing job!
go ahead please :)
@briziomusic Done : https://github.com/verdie-g/StoredProcedureEFCore/releases/tag/v0.3.0
@verdie-g thank you! I'm going to test and use it tomorrow
I still can't scaffold stored procedures. Are there any plans to include this on road map ?
@Kabindas This issue is in the Backlog milestone. This means that it is not going to happen for the 3.0 release. We will re-assess the backlog following the 3.0 release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.
@ajcvickers thank you for the feedback
"I still can't scaffold stored procedures"
-- The hard part is getting the tables/columns quickly and efficiently. I would volounteer to program it myself, this weekend... if I had access to the code. I'm sure Microsoft has code from Sql2Linq and EDMX to do this already. Anyways, here is the magic query to get all sp's and resulting columns from a database in under a second:
SELECT p.name, r.*
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;
I was considering adding this to a tt4 file and having a personal solution. I mean 100% of my objects that I access are always stored procs and never tables directly. I've programmed like that for 17 years... cleaner/faster/better, easier to maintain. Sql has multi-threading built in... 0 lines of code to add... so that's what I mean faster.
"I still can't scaffold stored procedures"
--Proposed Solution - 97 lines of code: 3 hours + 1 hour of googling yesterday
Note: adding a few "in" statements, probably reduces to 80 lines of code.
ie. "WHEN r.system_type_name in('smalldatetime','datetime',''datetime2','date','time') THEN 'DateTime'"
CREATE PROCEDURE usp_Entity_SP (@NameSpace VARCHAR(100) = 'WebApplication1')
AS
SET NOCOUNT ON
DECLARE @Counter INT = 1
DECLARE @End INT = 0
DECLARE @SP_Name VARCHAR(250) = ''
DECLARE @CS_Type VARCHAR(100) = ''
DECLARE @Column_Name VARCHAR(250) = ''
DECLARE @Column_Ordinal INT = 0
SELECT IDENTITY(INT, 1, 1) AS RowID
,p.NAME AS Sp_Name
,CASE r.system_type_name
WHEN 'bigint' THEN 'long'
WHEN 'smallint' THEN 'short'
WHEN 'int' THEN 'int'
WHEN 'UNIQUEIDENTIFIER' THEN 'Guid'
WHEN 'smalldatetime' THEN 'DateTime'
WHEN 'datetime' THEN 'DateTime'
WHEN 'datetime2' THEN 'DateTime'
WHEN 'date' THEN 'DateTime'
WHEN 'time' THEN 'DateTime'
WHEN 'float' THEN 'double'
WHEN 'real' THEN 'float'
WHEN 'numeric' THEN 'decimal'
WHEN 'smallmoney' THEN 'decimal'
WHEN 'decimal' THEN 'decimal'
WHEN 'money' THEN 'decimal'
WHEN 'tinyint' THEN 'byte'
WHEN 'bit' THEN 'bool'
WHEN 'image' THEN 'byte[]'
WHEN 'binary' THEN 'byte[]'
WHEN 'varbinary' THEN 'byte[]'
WHEN 'timestamp' THEN 'byte[]'
WHEN 'geography' THEN 'Microsoft.SqlServer.Types.SqlGeography'
WHEN 'geometry' THEN 'Microsoft.SqlServer.Types.SqlGeometry'
ELSE 'String'
END + CASE
WHEN R.system_type_name IN ('BigInt','Int','SmallInt','TinyInt','float','real','numeric','smallmoney','decimal','money','bit','UNIQUEIDENTIFIER'
,'smalldatetime','datetime','datetime2','date','time')
AND IS_Nullable = 1
THEN '?'
ELSE ''
END AS CS_Type
,replace(IsNull(r.NAME, 'Unnamed'), ' ', '_') AS Column_Name
,r.column_ordinal
INTO #Tentity
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r
WHERE r.system_Type_Name IS NOT NULL
SET @End = @@IDENTITY
PRINT 'using System;'
PRINT 'using System.Collections.Generic;'
PRINT 'using System.ComponentModel.DataAnnotations;'
PRINT 'using System.Linq;'
PRINT 'using System.Threading.Tasks;'
PRINT ''
PRINT 'namespace ' + @NameSpace + '.Models'
PRINT '{'
WHILE @Counter <= @End
BEGIN
SELECT @SP_Name = Sp_Name
,@CS_Type = CS_Type
,@Column_Name = Column_Name
,@Column_Ordinal = column_ordinal
FROM #Tentity
WHERE RowID = @Counter
IF @Counter > 1
AND @Column_Ordinal = 1
BEGIN
PRINT ' }'
PRINT ''
END
IF @Column_Ordinal = 1
BEGIN
PRINT ' public class ' + @SP_Name + 'Result'
PRINT ' {'
PRINT ' [Key]'
PRINT ' ' + @CS_Type + ' ' + @Column_Name + ' { get; set; }'
END
ELSE
PRINT ' ' + @CS_Type + ' ' + @Column_Name + ' { get; set; }'
SET @Counter = @Counter + 1
END
DROP TABLE #Tentity
PRINT ' }'
PRINT '}'
As a workaround, I'm combining query types, scalar functions and a fake, oracle-style V_Dual
view.
Migration for PostgreSQL:
CREATE VIEW "V_Dual" AS SELECT 'X' AS "Dummy";
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
BEGIN
-- What if this issued an UPDATE?
RETURN i + 1;
END;
$$ LANGUAGE plpgsql;
EF Configuration:
public class Dual
{
public char Dummy { get; set; }
}
public class MyContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<Dual>()
.ToView("V_Dual");
}
[DbFunction]
public static int Increment(int i) {
throw new Exception();
}
}
Finally an example of a query:
await _context
.Query<Dual>()
.Select(_ => MyContext.Increment(2))
.SingleAsync()
.ConfigureAwait(false);
I wonder if there are any downsides to this workaround? Is there a risk of the output of the function to be cached, ie. is it safe to issue eg. UPDATE
in the function?
@natemcmaster I donât think this should have been closed? I think your merge of Microsoft.Data.Sqlite in #13843 may have closed some issues accidentally. I wonder if this has happened before with some of the repo merges (and it will likely happen in future đ)
Oops. Yes, unintentional close caused by merging repos together. It happens again, just let me know and I can re-open.
If you are using sql server, just create an EF project using the framework and copy over the generated data classes.
If you are using sql server, just create an EF project using the framework and copy over the generated data classes.
You can only do that on Windows... and having a framework project just for scaffolding doesn't seem the best solution :/
If i return the SELECT * FROM tablename, the procedure calls works, but if i return custom select statement result ( using joins on two tables, in here its class: SP_GetAssignedLockers) ,
```C#
public class SP_GetAssignedLockers
{
public string LockerNumber { get; set; }
public int EmployeeNumber { get; set; }
public string EmployeeName { get; set; }
public DateTime AssignedDate { get; set; }
public string AssignedBy { get; set; }
}
This call doesn't work.
Am i missing something ?
```C#
public IEnumerable<SP_GetAssignedLockers> GetAllWithSP()
{
var a = RepositoryContext.Set<SP_GetAssignedLockers>().FromSql("dbo.SP_GetAssignedLockers").ToList();
return a;
}
@d4dpkrajput Please open a new issue and include a small, runnable project/solution or complete code listing that demonstrates the behavior you are seeing.
Hi ajcvickers, I am done with the code. I created a class ( Entity ) which is the return type of the stored procedure, created an [ID] column in that class. Because it requires a primary key in the class. and then
MyCode :
C#
public IEnumerable<SP_GetAssignedLockers> GetUsedLockers()
{
return RepositoryContext.SP_GetAssignedLockers.FromSql("SP_GetUsedLockers")
.AsNoTracking().ToList();
}
To call stored procedure in the Entity Framework Database First approach code , we need following things
That what i observed.
Thanks for your help and support !!
For me, two of the most useful features in EF6 is:
The ability to visualize my data model in Visual Studio, especially since I largely use the DB first approach.
The use of Function Imports to import and call complex stored procedures.
So I can live without point 1, but much of my work involves the use of complex stored procedures that simply don't lend themselves being converted to some LINQ implementation or EF Core workaround.
I can't understand why it seems to be so hard to reproduce in EF Core what's already been done in EF6 but until such time that SPs are supported I can see no incentive to move to EF Core.
The ability to visualize my data model in Visual Studio, especially since I largely use the DB first approach.
There are several 3rd-party tools available which do this, you may want to take a look.
The use of Function Imports to import and call complex stored procedures.
You can call complex stored procedures with EF Core. Reverse engineering them from the database isn't supported natively, but again one of the 3rd parties may be able to do this.
@roji thank you for your reply but what you are really saying is that I should look at an alternative ORM tool from another vendor and ditch EF Core entirely.
@ian-m-cooper I think @roji is suggesting 3rd party tools for designer, not for engine. I know that LLBLGenPro supports code generation for EF Core and has a nice and powerful designer. However I would consider its engine as well.
Yeah, as @MihaMarkic wrote, there are 3rd-party tools that work very well with EF Core and do exactly what you're asking for - it doesn't mean ditching EF Core at all. And there are indeed also non-EF Core alternatives like LLBLGen if you want to go that way.
Which tool allows use of stored procedures generated as functions? Many of those tools describe creating POCO classes to represent entities, but what we need is the already existing function from stored procedure generation to be included in ef core.
Since it is the main element used for most web applications (to map db content to view models), it should have been a very high priority from the outset.
6 years have passed! How many time we should wait this functionality?!!!
It main functionality for rapid development.
6 years have passed! How many time we should wait this functionality?!!!
It main functionality for rapid development.
Absolutely, how something, apparently, so simple, can take so long :(
@mathewsun @Kabindas See our release planning process
Please, have a look there:
https://github.com/DarioN1/SPToCore
I have created a kind of scaffolder for Stored Procedure, I'm using it in a new project that uses an existing database with more than 300 stored procedures.
We don't need a designer, but at least generating the model for the return type of stored procedure is highly needed in our project. That is the only limitation which is holding us from migrating to .Net Core
May be before before bringing other new features, MS should be considerate about bringing this core feature of EF.
My two cents.
@the-super-coder - It has been six (6) years, I doubt that this will become a priority; I think we are the minorities using stored procedure mapping, in fact, all my projects use stored procedures, I would love this enhancement. However, "and I could be wrong," stored procedure mapping is probably not needed by too many developers since they are mapping directly to tables/views.
FWIW, its high on the list for new features in EF Core Power Tools.
This is a very supernews @ErikEJ!!!
Import Stored Procedure Function in .Net Core
https://github.com/NikhilVirani/DotnetCore.DB
I have lost focus on EF Core changes - are TVP parameters already supported or still not?
Latest release of EF Core Power Tools supports mapping / reverse engineering of SQL Server stored procedures
hmm I'm not sure is this answering my question - reverse engineering is a tool for generate code that I can write manually, it is cool they work with SP but my question is about TVP. Is that generated code (or code that I can write manually) can use Table-Valued Parameters?
@bigdnf that was not a reply to your question, but information for people following this issue.
Yes, TVP SqlParameter with a stored procedure is supported when using FromSqlRaw.
@ErikEJ Although SqlParameter with a stored procedure is supported, named parameters are not supported yet in EF Core.
@ErikEJ sounds interesting! I can't find too much information on the repo on how to use the tool for mapping. Got any resource to point to?
There is info on the wiki and I also have this blog post https://erikej.github.io/efcore/2020/08/10/ef-core-power-tools-stored-procedures.html
@roggan87
Thanks @ErikEJ I'll definitely check it out!
Hi @ErikEJ. I have just discovered EFCore Power Tools and, for me at least, it looks to be exactly the missing piece from EFCore for those of us that want to do database first development and use a lot of stored procedures.
I do have one question though and I apologise if this seems a bit of a newbie question. In the model diagram dgml view, what is the convention you are using for relationship cardinality. I am used to diagrams where there is a cardinality at each end of the relation (EF6 style), but your diagrams seem to use a single cardinality on a relation with an arrow and this has confused me. It does not appear to be Chen, UML, Crows Foot. Is there a name for this type of approach ? I have attached an example of a 1 to Many relationship.
Many thanks.
I honestly cannot remember why this notation is used, but the reason to have text labels is mainly due to constraints from the diagram format.
If you have ideas for a better text label, feel free to suggest or even create a PR.
Looks like there are some proposals here: https://www.gatevidyalay.com/cardinality-in-er-diagram/
Most helpful comment
6 years have passed! How many time we should wait this functionality?!!!
It main functionality for rapid development.