linq to stored procedures multiple select - c#

MSDN docs say that I can write a stored procedure like this
CREATE PROCEDURE MultipleResultTypesSequentially
AS
select * from products
select * from customers
then read it from LINQ like this
IMultipleResults sprocResults =
db.MultipleResultTypesSequentially();
// First read products.
foreach (Product prod in sprocResults.GetResult<Product>())
{
Console.WriteLine(prod.ProductID);
}
// Next read customers.
foreach (Customer cust in sprocResults.GetResult<Customer>())
{
Console.WriteLine(cust.CustomerID);
}
what if one of my select statements return something other then a regular table object - with a join or just selecting certain columns?
how do I let LINQ know that I want to read the next SELECT ??? basically , what I'm wondering is this example from MSDN reading Products first then Customers because they are written in that order in the stored procedure , or is writing .GetResult<Customer>() telling c# to find the result that maps to type Customer? and also what would the foreach loop look like for this unknown type?

I did a quick test with a similar stored procedure and found that if your foreach loops are not in the correct order, an InvalidOperationException is thrown, so it doesn't look like C# is able to find the correct result based on the type used in GetResult<>.
As for your select statement returning something other than a table, if you drag a stored procedure from the Server Explorer onto the Linq to Sql designer, the designer will autogenerate a class based on procedures output. I created a procedure with a couple of joined tables, neither of which existed in my project, and Linq to Sql created a type for me, named like StoredProcedureNameResult, so a procedure called GetCreditCard had a type named GetCreditCardResult.

Related

How can we define complex type for a stored procedure that accepts dynamic query as input [edmx]

I have a stored procedure like this
create proc usp_ProjectName_DBQuery
#strDBQuery varchar(8000)
as
begin
exec (#strDBQuery)
end
So this will accept any DBQuery and it will execute it in the server.
Now my problem is this will return n number of columns based on the query.
For example if I pass in select x,y from db it will return two columns, but if i pass in select * from db it will return n columns, it sometimes may not return anything
So how can I define a complex type for this stored procedure!? Please help
#marc_s is right this is not something you can do in EF (without third party library).
Entity framework doesn't really like that.
You have 2 options:
Use ADO.NET instead as suggested in the comments
Change your stored procedure to return the same number of column even of they are empty fields.

Retrieving records from table where a column may have multiple rows of data

I have a database with several tables and I am using the following query to return a record that matches a string(Name).
In the MHP table there is a Name field(primary key), Num_Sites and a few more, but these are the only ones I am concerned with.
In the MHP_Parcel_Info table there are many fields with one of them being Name(foreign key). There is a parcel_id field and in some case there may only be one parcel for one name, but there may also be many parcels for a Name.
As it is now my query will return one of the rows for instances where there are multiple parcels for a name.
What I would like to do is: if there is more than one parcel for a Name, have all the parcels put into a list(so I can display in listbox on form).
My SQL skills are limited and I don’t know how I would go about doing something like this.
SELECT MHP_Parcel_Info.*, MHP.NUM_SITES FROM MHP_Parcel_Info INNER JOIN MHP ON " +
"(MHP_Parcel_Info.MHP_NAME = MHP.MHP_NAME) WHERE MHP_Parcel_Info.MHP_NAME='" + strValue + "'"
This is not something you can do directly in SQL. There's no way to select data in a parent/child structure in a SQL query - you have to do that as a post-processing step.
Since this is tagged as C# and Winforms I'm assuming this is from inside a .Net app. You will need to execute the query as you have it above, then in C# you can use the LINQ GroupBy extension method on the result to group the results into a list of IGrouping objects which use the name as the key, and has all of the parcel info as the items in the list.
Even better, if you are using (or can use) LINQ to SQL or Entity Framework you can just write a linq query that fetches the data from the database and does the grouping all at once.

Use stored procedure in Entity Framework (code first)

I use this code to define my stored procedure
CREATE PROCEDURE [dbo].[SP]
(#Country NVARCHAR(20))
AS
BEGIN
SET NOCOUNT ON;
SELECT c.*,O.* from Customers
as c inner join orders O on c.CustomerID=o.CustomerID
where c.Country=#Country
END
and this is my C# code:
IList<Entities.Customer> Customers;
using (var context = new NorthwindContext())
{
SqlParameter categoryParam = new SqlParameter("#Country", "London");
Customers = context.Database.SqlQuery<Entities.Customer>("SP #Country", categoryParam).ToList();
}
Problem is here :
I want to message the data from Orders table and my stored procedure generate this to me. How can I get the Orders data in my C# code? Remember I want to execute this stored procedure only once.
Take a look at Does Entity Framework Code First support stored procedures? and http://blogs.msdn.com/b/wriju/archive/2011/05/14/code-first-4-1-using-stored-procedure-to-insert-data.aspx which talk about executing a stored proc via a DbContext object.
I think perhaps your issue is that you aren't getting the orders back as part of your query? is this correct? If so this is because you are only selecting customers. You need to either create an object of the same schema as you expect to be returned from your query (ie that has both customer and order properties) or select into a dynamic type (eww).
Having said that i strongly recommend doing this in linq instead:
from c in context.Customers.Include(c=>c.Orders)
where c.Country == country
select c;
This is a much better approach as you are using EF for what its designed for and not querying for something which doesn't fit your model

Why linq fail to get temp table values

work on C# vs2008. I have a stored procedure ,This procedure holds temp table ,i need to get the temp table values.My sql query is bellow:
create procedure [dbo].[TestProcedure]
as
SELECT * INTO #temp1 from(select * from DischargePort) as b
select * from #temp1
drop table #temp1
My above query has a temp table named #temp1.After run this query in sql-server-management i get result ,but when i try to execute this procedure in linq ,I get no result.My linq syntax is bellow:
var r = ProviderName.TestProcedure();
Can anybody tell me why this problem arise,How to overcome this problem.Hope any body not say that linq can not handled the temp table or this kind of word.if have any query plz ask .Thanks in advance.
I don't think this is anything to do with the temporary table, but rather that Linq does not know what output is to expected.
With Dotnet Framework 4, this is easy, as you can do something like
(from r in ProviderName.TestProcedure().AsDynamic()
select new { r.Id, r.Description}).ToList()
(assumes Id and description are fields in DischargePort)
Otherwise, you need to do something in your designer to tell Linq what your procedure outputs. I have never had to do this, but perhaps this article will help.
When I think about it, in this particular case, you should be able to do something like
var results = (from r in ExecuteQuery<DischargePort>("exec TestProcedure")
select r ).ToList();
i would start by downloading linqpad to see the sql that linq is emitting, this may provide some clues. you could also use the sql profiler tool to see what query is being run.

LINQ (L2E) with stored procedure and IQueryable

Consider a normal Linq expression will be something like this:
(This is just a sample to make things more understandable)
IQueryable<Person> personQuery= (from ppl in PersonContext
select ppl).ASQueryable();
List<Person>personList = personQuery.where(x => x.age==13).ToList();
So if I decided to put the 1st part of the linq query inside a stored procedure,
things will work out something like this.
IQueryable<Person> personQuery= PersonContext.sp_RetrievePerson().ASQueryable();
List<Person> personList = personQuery.where(x => x.age==13).ToList();
So for the question, I believe that the 1st method only sends the sql call when toList() is called.
In another words, the query sent to sql for execution will be
Select * from Person where age=13
But for method 2, how many times will this query be sent for execution?
If it is only sent 1 time, does it make it redundant to call the stored procedure as stored procedure is known for having a faster execution and how will the query sent to sql look like?
I am not sure about this one, but PersonContext.sp_RetrievePerson() returns an ObjectResult, which internally uses a DbDataReader. That means that the stored procedure is called once, the
personQuery.where(x => x.age==13) iterates over the resulting rows and filters out not matching objects.
By using stored procedures for this you might get a small performance gain on querying the database, but you have to evaluate each object in the persons table, AFTER reading it from the database. So I think in this scenario using stored procedures only makes sense, if you provide a parameter age to the stored procedure for filtering the results already in the database.

Categories

Resources