The goal
Count the results returned from a stored procedure.
The problem
I have the following code on my ProductsController:
[HttpGet]
public ActionResult DailyOffers()
{
var productsList = Products.BuildOffersList();
ViewBag.Title = String.Format("Ofertas de hoje ({0:dd/MM/yyyy})",
DateTime.Now);
ViewBag.CategoryProductsQuantity = ??;
ViewBag.CurrentCategory = "Daily-Offers";
return View(productsList);
}
As you can see, there is a builder on this method. This builder returns the Stored Procedure result. And I want to count the number of results that this procedure returns.
What I'm thinking about
Maybe this?:
ViewBag.CategoryProductsQuantity = productsList.Count;
Technical details
I'm using C#.NET + MySql + Entity Framework 5 + Razor Engine.
Assuming that Products.BuildOffersList(); does in fact return a List (and not an IEnumerable/IQueryable) then what you've suggested should be fine and won't result in multiple enumerations.
ViewBag.CategoryProductsQuantity = productsList.Count();
Use parameter "output" on Stored Procedure and create parameter "out" on your method.
#ROWCOUNT INT OUTPUT
SELECT
FROM
WHERE
SET #ROWCOUNT = ##ROWCOUNT
Related
Previously this worked well and recently the line stop working. This code uses the DB context to run a procedure and return it in List format. For some reason I am not seeing the error, I just see the action fail because it is not executing.
I ran the stored procedure in SQL Server and see the desired results, just not seeing it happening from the application layer.
[Http.Route("postsearch")]
public async Task<IHttpActionResult> PostSearch(SearchInputDTO srequest)
{
var searchString = srequest.SearchValue.ToString();
List<output> seResult = new List<output>(_output.searchLog(searchString)); /*This line stopped working*/
return Ok(seResult);
}
Stored procedure:
SET FMTONLY OFF
GO
SET NOCOUNT ON
GO
ALTER PROCEDURE [dbo].[searchLog]
#searchValue VARCHAR(150)
AS
SELECT *
FROM [dbo].[output]
WHERE CONTAINS (*, #searchValue)
Implementation in Entity Framework
public virtual int searchLog(string searchValue)
{
var searchValueParameter = searchValue != null ?
new ObjectParameter("searchValue", searchValue) :
new ObjectParameter("searchValue", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("searchLog", searchValueParameter);
}
This should return the rows from the query.
The Solution I found was to modify the output of the stored procedure in Visual Studio.
Try removing the new instance of the list and just have it like this
List<output> seResult = _output.searchLog(searchString);
Update stored proc to
#searchValue varchar(150)
AS
BEGIN
SELECT
[ColumnName1]
,[ColumnName2] ...etc...
FROM [dbo].[output]
WHERE CONTAINS (*,#searchValue)
END
I'm trying to use ExecuteSqlCommandAsync from EF Core to get the result of a select query in a somewhat odd legacy stored procedure that has an empty RETURN statement.
The stored procedure looks like this:
CREATE PROCEDURE [dbo].[SelectNextCounter]
(
#CounterName nvarchar(50)
)
AS
UPDATE counter
SET NextValue = NextValue + 1
WHERE CounterName = #CounterName
SELECT NextValue
FROM counter
WHERE counterName = #CounterName
RETURN
GO
Using this code I'm able to access the RETURN value of the stored procedure (though what I'm really interested in is NextValue):
var counterName = new SqlParameter
{
ParameterName = "#CounterName",
Value = "CustomerNumber",
SqlDbType = SqlDbType.NVarChar
};
var returnValue = new SqlParameter
{
ParameterName = "#return_value",
Direction = ParameterDirection.Output,
SqlDbType = SqlDbType.Int
};
await _context
.Database
.ExecuteSqlCommandAsync(
"EXEC #return_value = SelectNextCounter #CounterName", counterName, returnValue
);
I can then get the value through returnValue.Value (which is always 0, because of the empty RETURN statement). However, is there any way to get the value from NextValue using EF Core? Seems like FromSql might work but I'm really just interested in getting a single value back, not an entity. This answer seems to do what I want but I would rather use EF Core than SqlCommand, if possible.
It has to be FromSql. Not possible in EF Core 2.0. Possible in EF Core 2.1, but a bit more complicated than needed, because SQL queries returning primitive types are still not supported. So you need to utilize Query Type like this:
First you need to create a "query type" class which will hold the result:
public class SelectNextCounterResult
{
public int NextValue { get; set; }
}
Second you need to register it in your OnModelCreating override:
modelBuilder.Query<SelectNextCounterResult>();
Then you can use it to call your SP
var counterName = "CustomerNumber";
var result = await context.Query<SelectNextCounterResult>()
.FromSql($"SelectNextCounter {counterName}")
.FirstAsync();
You could do something like the following. I wrote my example to run only in SQL but the concept should be the same for the c# portion. I would recommend using SqlCommand if you ever intend this to be extensible. Return also only every works with integers.
Since you can return any integer value, you can just say Return [integer]
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/return-transact-sql?view=sql-server-2017
CREATE PROCEDURE [dbo].TestProc
AS
DECLARE #returnVal INT = (SELECT 2)
RETURN #returnVal
GO
DECLARE #newReturnVal INT
EXEC #newReturnVal = [dbo].TestProc
SELECT #newReturnVal
Also you should change the query to use UPDATE … OUTPUT so that two sessions won't get the same value. EG
CREATE PROCEDURE [dbo].[SelectNextCounter]
(
#CounterName nvarchar(50)
)
AS
UPDATE counter
SET NextValue = NextValue + 1
OUTPUT INSERTED.NextValue
WHERE CounterName = #CounterName
GO
I am using database-first approach for Entity Framework in my ASP.NET project. I have a stored procedure that has an output parameter #TotalCount and it returns a result set using a SELECT statement.
When I add the stored procedure in my MyDbContext.edmx file, the MyDbContext.cs has a function that returns an int (probably the output parameter) that is automatically generated for the stored procedure.
How can I access both the output parameter as well as the result set with this approach?
The stored procedure snippet is given below. Basically I am trying to do pagination in the stored procedure.
CREATE PROCEDURE [dbo].[sp_GetDetailsForStudent]
#StudentId BIGINT,
//....
#OrderBy NVARCHAR(max),
#Page INT OUTPUT,
#Items INT = 200,
#TotalCount INT OUTPUT
//.....
SET #SortSql = N'SELECT * FROM #tmpTable'
//......
EXEC sp_executesql #SortSql;
In the MyDbContext.cs file
public virtual int sp_GetDetailsForStudent(parameters ...){
//......
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("sp_GetDetailsForStudent", input parameters..., totalCount);
}
First you need to update your EDMX model so that your function
public virtual int sp_GetDetailsForStudent(parameters ...){....}
Should look like
public virtual ObjectResult<YourResult_type> sp_GetDetailsForStudent(parameters ...){....}
For refreshing EDMX model go hear
You might need to choose "Create New Complex Type" option instead of "Update" as suggested in above link.
Then to fetch the result you can use below code
ObjectParameter outParam1 = new ObjectParameter("outParameter", typeof(long));
var db = new YourDbContext();
var res = db.sp_GetDetailsForStudent(parameter1,parameter2,outParam1 );
foreach (YourResult_type item in res)
{
var prop1= item.property1;
}
var outParam1Value= outParam1.Value;
have a stored Procedure that do some operation and return 1 or 0 as below.
CREATE PROCEDURE dbo.UserCheckUsername11
(
#Username nvarchar(50)
)
AS
BEGIN
SET NOCOUNT ON;
IF Exists(SELECT UserID FROM User WHERE username =#Username)
return 1
ELSE
return 0
END
Using linq I tried to get return value. But i am getting the output as -1 always.
Below is my Linq code :
using (PlanGenEntities3 entity2 = new PlanGenEntities3())
{
var result = entity2.Entity_test_GetHoliday();
string output = result.ToString();
}
How to solve this ?
Just declare your scalar variable as a output parameter for SQL query, then in the code you could retrieve its value this way:
```
using (PlanGenEntities3 myContext = new PlanGenEntities3())
{
var outputParameter = new System.Data.Objects.ObjectParameter("OutputParameterName", typeof(int));
myContext.Entity_test_GetHoliday(outputParameter );
Console.WriteLine(outputParameter.Value);
}
```
I suppose there is way to access the default scalar output of your SP in the similar manor.
If he had it as an output parameter it would automatically show as a reference parameter of the proper corresponding data type in the LINQ call.
He wouldn't really need to create a parameter object to contain that.
I have a stored procedure which returns maxNum. I can see the return value in the debugger: maxNum[0] has the value. I saw it in the debugger.
IEnumerable<int?> maxNum = DB.uspGetNextTestNumber();
How to read the value from it.
The above code is calling a stored procedure from ADO.NET Entity model.
ASP.NET MVC. VS2013. Windows 8.1 64 bit.
My stored procedure looks like this:
CREATE PROCEDURE [dbo].[uspGetNextTestNumber]
AS
SET NOCOUNT ON;
SELECT MAX(testnumber) + 1 as NextNumber
FROM [ProductTesting].[dbo].[PtTest] AS sp
GO
IEnumerable maxNum = DB.uspGetNextTestNumber();
List<int?> lst = maxNum.ToList<int?>();
foreach (var item in lst)
{
if (item.HasValue)
{
string str = item.Value.ToString();
// str has the value
}
}
Easy when using System.Linq:
int? number = DB.uspGetNextTestNumber().FirstOrDefault();