Stored procedure returning dynamic columns in Entity Framework - asp.net-mvc

I have a function calling a SQL Server stored procedure using Entity Framework 6.2.
The stored procedure returns a result set which has different number of columns on each call, and column names may vary on each call.
Function getListOfDocs() As JsonResult
Try
Using entities As PromatEntities = New PromatEntities()
Dim param(1) As SqlParameter
param(0) = New SqlParameter("#ProjID", SqlDbType.Int)
param(0).Value = vProjectId
Dim query = entities.Database.SqlQuery(Of "help required here")("sp_EIP_IPSSDocMaster_Get", param) // cannot handle this case as entity framework needs type
Dim lstDocs = query.ToList
End Using
Return Json(New With {lstDocs}, JsonRequestBehavior.AllowGet)
Catch ex As Exception
ClsCommon.ExceptionManager(ex)
Return Nothing
End Try
End Function
But Entity Framework doesn't allow anonymous types in database.SqlQuery. Can anyone suggest a way to solve the issue and get the anonymous type data to view?

Related

Stored procedure "weird" result set with Power Tools EF Core 5

I have installed EF Core 5 Power Tools to Add a DB with stored procedure to an ASP.NET Core project. the models are successfully generated by Power Tools and the tables work fine; but when i try to retrieve a result set out of a stored procedure and store it to a ViewBag to display on the View, the value stored at Viewbag is weird and has nothing to do with a result set.
Here is the stored procedure code at db, which is pretty simple, just to test Power Tools:
CREATE PROCEDURE retTable (#P INT)
AS
BEGIN
SELECT * FROM STU WHERE ID=#P;
END;
Controller:
public IActionResult Index()
{
schoolContext s = new schoolContext();
schoolContextProcedures sp = new schoolContextProcedures(s);
var t = sp.retTableAsync(20); // The built is perfectly done, but the value store instead of result set is weird
ViewBag.test = t;
return View();
}
and just added a #View.Bag to the view to make sure it's displayed, Though the app's built is done successfully without any error, This is what's displayed at the View instead of ViewBag value:
System.Runtime.CompilerServices.AsyncTaskMethodBuilder1+AsyncStateMachineBox1[System.Collections.Generic.List`1[WebApplication2.Models.DB.retTableResult],WebApplication2.Models.DB.schoolContextProcedures+d__3]
Tried to convert the result set to a list or something else but it's not working :|
Anyone know how to fix it?
The value stored in it is not "weird", its a Task.
Since your method is async, you should await for the result of the returned task, not the "return" itself, as this is only a reference to the task that is executed asynchronusly.
As martin smith mentions, just:
var t = await sp.retTableAsync(20);
Otherwise you are adding a task as the viewbag property, instead of the task result once completed

Calling Stored Procedure From Entity Framework that returns table with variable columns

I am using ASP.NET MVC 3 and EF 4.x
I have a procedure that returns a result set but the columns are not fixed (it may return 25 columns or may be 40 or 50).
How can I call this stored procedure from Entity Framework?
When I use function import it asks for an Entity. But I cannot select it as none of the columns is fixed.
Entity Framework is not the right tool for this. It is good at statically defined data structures, not at dynamic ones.
There are better tools for this. I would recommend Dapper, created by Marc Gravell. It's easy as pie. Just get the NuGet package and type something like
using Dapper;
using (var cnn = new SqlConnection(myConnectionString))
{
cnn.Open();
var p = new DynamicParameters();
p.Add("#params", "Id=21");
var results = cnn.Query(sql:"GetMyData",
param: p,
commandType: CommandType.StoredProcedure);
foreach(IDictionary<string, object> result in results)
{
// Do something here.
}
}
Query is a Dapper extension method, result is a DapperRow, which is a private class that implements IDictionary<string, object>, so you can just access your data as a dictionary per record.
Aside from being easy to use, it's lightning fast too.

LLBLGenProQuery Vs IQueryable

I am using LLBLGen Pro, MVC 3 and VB.NET. I am trying to return an object of Iqueryable but i am getting following exception
Unable to cast object of type 'SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery1[Mail.DAL.EntityClasses.TblCostCentreEntity]' to type 'System.Linq.IQueryable1[Mail.Model.CostCentre]'.
I am not sure whats the difference betweeen LLBLGenProQuery and IQueryable? How do i return an IQueryable object using LLBLGenPro? My code is as following:
Public Function GetAllCostCentres() As IQueryable(Of Model.CostCentre) Implements ICostCentreRepository.GetAllCostCentres
Mapper.CreateMap(Of TblCostCentreEntity, CostCentre)()
Dim metaData As New LinqMetaData
Dim q = From p In metaData.TblCostCentre _
Select Mapper.Map(Of IQueryable(Of CostCentre), TblCostCentreEntity)(p)
'Dim t As IQueryable(Of CostCentre) = Mapper.Map(Of CostCentre)(q)
'Select New CostCentre With {.Active = p.Active, .CostCentre = p.CostCentre, .CreatedBy = p.CreatedBy, .DateCreated = p.DateCreated, .DateLastModified = p.DateLastModified, .ModifiedBy = p.ModifiedBy, .CostCentreID = p.CostCentreId}
Return q
End Function
IQueryable
(http://llblgen.com/documentation/3.5/LLBLGen%20Pro%20RTF/hh_goto.htm#Using%20the%20generated%20code/Linq/gencode_linq_gettingstarted.htm#LinqMetaData)
It's a query that will make the compiler produce code which creates at runtime a tree of Expression instances, representing the entire query, in short an Expression tree. An Expression tree is not executable directly, it has to be interpreted to execute what is specified inside the Expression tree. This is what a Linq provider, like Linq to LLBLGen Pro, does: it accepts an Expression tree, translates it into elements it can understand, interprets these elements and produces an executable form of this query.
ILLBLGenProQuery
(http://llblgen.com/documentation/3.5/LLBLGen%20Pro%20RTF/hh_goto.htm#Using%20the%20generated%20code/Linq/gencode_linq_gettingstarted.htm#ILLBLGenProQuery)
An interface defined on the IQueryable elements produced by LinqMetaData. This interface allows you to execute the query by calling the Execute method. The advantage of this is that you can get the query result in its native container, e.g. an entity collection. Another advantage is that to obtain a list of the results, the provider doesn't have to traverse the results in full, and copy over the results in a List: the returned results are already in the container they're initially stored in.

Returning DbQuery to view that requires IEnumerable

The problem:
Exception Details: System.InvalidOperationException: The model item
passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1[System.Int32]', but this
dictionary requires a model item of type 'migros.Models.State'.
What I'm trying to do
I need to pass the result of the following linq query to a View.
using (var db = new migros_mockEntities1())
{
var listOfIdeas = (from x in db.States select x.ID);
return View(listOfIdeas);
}
The View requires IEnumerable, but it seems I can't cast the result of the linq query to IEnumerable.
I'm using entity framework database first approach.
The problem is that you trying to return ObjectQuery from within the using block.
Try to materialize your object-set
var listOfIdeas = (from x in db.States select x.ID).ToList();
Also, dont forget, that dealing with context can be tricky.
In your case var listOfIdeas = (from x in db.States select x.ID) is just a query, that will run only when you'd begin to iterate over it. So, if context gets already disposed you'd get an exception, trying to use listOfIdeas.

CLR Stored Procedure

I wish to use the Cryptography API in CLR stored procedure.
I have created a CLR stored procedure and written a select statement
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = #"select * from Employee";
SqlDataReader rdr = cmd.ExecuteReader();
Now I wish to filter the results using the employee Number which is stored in encrypted form in database for which I am going to use the Cryptography methods.
Now I am stuck with how to go about filtering the records from the SqlDataReader.
I want the return format as SqlDataReader, as to return multiple records from CLR stored procedure there is one method SqlContext.Pipe.Send() and this method accepts only SqlDataReader objects.
Please guide me.
I'm looking at a similar problem where I want to do some manipulation before returning the results.
The only way I can see at the moment is to use:
// Note you need to pass an array of SqlMetaData objects to represent your columns
// to the constructor of SqlDataRecord
SqlDataRecord record = new SqlDataRecord();
// Use the Set methods on record to supply the values for the first row of data
SqlContext.Pipe.SendResultsStart(record);
// for each record you want to return
// use set methods on record to populate this row of data
SqlContext.Pipe.SendResultsRow(record);
Then call SqlContext.Pipe.SendResultsEnd when you're done.
If theres a better way I'd like to know too!

Resources