Why do I have to invoke function DataContext ExecuteMethodCall twice - c#

I am using linq to sql to execute SPs, but getting this issue for a few of the SPs. I have to execute the function ExecuteMethodCall twice to get the result. The first call does not even go to SQL Server. I used SQL Profiler to check if the SP was executed, but I get this in profiler:
RPC:Completed exec sp_reset_connection
The subsequent call to ExecuteMethodCall actually executes the SP and gets data.
[Function(Name="dbo.Example_SP_To_Get_List")]
[ResultType(typeof(Example_SP_To_Get_List_getResult1))]
[ResultType(typeof(Example_SP_To_Get_List_getResult2))]
public IMultipleResults Example_SP_To_Get_List([Parameter(Name="SEARCH", DbType="VarChar(50)")] string sEARCH, [Parameter(Name="PAGE", DbType="VarChar(1)")] string pAGE, [Parameter(Name="ACTIVEFILTER", DbType="VarChar(4)")] string aCTIVEFILTER)
{
//first invocation, returns nothing, does not even call the SP (SQL Profiler does not show the sp call)
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), sEARCH, pAGE, aCTIVEFILTER);
//second time, it executes the SP and returns the result
result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), sEARCH, pAGE, aCTIVEFILTER);
return ((IMultipleResults)(result.ReturnValue));
}
Please help me find why this is happening to few SPs, while others work fine.

If a SP returns multiple result sets, then the caller function must fetch all result sets in sequence. In above case, the SP returned two result sets and I was only fetching the second result set.
Using following code resolves the issue:
var spResults = dbLayer.Example_SP_To_Get_List();
var result1 = spResults.GetResult<Example_SP_To_Get_List_getResult1>().ToList();
var result2 = spResults.GetResult<Example_SP_To_Get_List_getResult2>().ToList();
Not sure if it is the best way, but it resolved my issue.

Related

Sequence contains no elements in asp core and sql server 2016

I need to return info from database with T-SQL and I'm using dapper.
I've written this code:
SELECT *
FROM UserActivetionCode UA
WHERE UA.Username=#Username
AND UA.ActivetionCode= #ActivetionCode
AND UA.ExpireTime > GETDATE()
and I'm using this code:
var find = await roleConnection.QueryFirstAsync(command, new {
#ActivetionCode = ActivetionCode,
#Username = Username });
but it shows me this error:
Sequence contains no elements
This error means that the query didn't return any results.
If you don't want to get it, use QueryFirstOrDefaultAsync.
This will result with default(T) (T being whatever datatype the query should return) if the query returned no rows.
However, QueryFirst implies a known order in the resultset, which your query does not provide (as it doesn't have an order by clause) and in any case, I suspect that the combination of Username and ActivetionCode should probably be unique. In that case, I would go with QuerySingleOrDefault, which will throw an exception if the query returned more than one result.

Methods executing out of order when using Linq Select

I have a series of methods that do some insertions into the database in a pretty set order. However, I'm running into an issue where one of the methods is firing off before the other method is called, unless I put a breakpoint in.
My initial thought was that due to me passing around IEnumerables, the method wasn't firing off until the Controller was returning the object, but after converting everything to lists, the error still occurs.
My code looks something like the following:
// controller
public IActionResult CreateConversation([FromBody] CreateConvoRequest model)
{
var userId = ViewBag.UserData.UserID;
model.message.UserFrom = userId;
model.users.Add(userId);
var result = MessagingLogic.CreateConversation(model.conversation, model.message, model.users);
return Json(result);
}
// Logic
public static Conversation CreateConversation(Conversation conversation, ConversationMessage message,
List<int> users)
{
conversation.DateCreated = DateTime.Now;
conversation.LastUpdated = DateTime.Now;
var convo = SaveNewConversation(conversation, users);
message.ConversationId = convo.ConversationId;
SendMessage(message);
return convo;
}
public static Conversation SaveNewConversation(Conversation conversation, List<int> users)
{
conversation = SaveConversation(conversation);
conversation.Users = users.Select(n => CreateConversationUser(conversation.ConversationId, n)).ToList();
// the above linq executes some SQL insertions and returns the new object
return conversation;
}
public static ConversationMessage SendMessage(ConversationMessage message)
{
if (message.CloseConversation) CloseConversation(message.ConversationId);
return SaveMessage(message);
}
What appears to be happening is that SendMessage is being called before CreateConversationUser. This is turn causes my messages not to be saved for the users as they aren't saved into the database until after the SendMessage method is called.
However, if I put a breakpoint on SaveNewConversation method, everything works as intended.
Edit
So after some more tinkering, adding the ToList to my Linq Selected corrected the issue with it executing out of order. However, my SendMessage SQL statement is using a INSERT INTO SELECT. It appears that the users often haven't been inserted into the database by the time the SendMessage sql executes.
For example, 2 of my users were inserted at 2017-09-20 10:29:35.820 and 2017-09-20 10:29:35.823 respectively. However, the message was inserted at 2017-09-20 10:29:35.810.
It appears something odd is happening on the SQL server.
Edit 2
Further testing is putting the entirety of the blame on SQL Server. I ran the SQL Profiler tool and the calls are coming in, in the correct order. However, there is only roughly a 3 millisecond delay between the last user being inserted and the messages being inserted.
If I place a sleep statement between the user insert and the message insert of a couple hundred milliseconds, it works as intended. I'm not quite sure how to address this issue, but it no longer appears to be executing out of order.

EF Linq QUery cause lock compared to SQL

I have a simple count query using LINQ and EF:
var count = (from I in db.mytable
where xyz
select I).Count();
the code above shows the query being locked in the database.
while the execute sql executes right away:
var count = db.SqlQuery<int>("select count(*) from mytable where xyz").FirstOrDefault();
the code above returns immediately.
I few have suggested to remove the .ToList() which I did and not difference. One thing is that this only happens on the PROD server. The QA server executes pretty fast as expected. But the prod server shows that it gets suspended. I suspect this could be a data storage limitation or server related. But wanted to make sure I am not doing something stupid in the code.
UPDATE:
One thing I noticed is the first time it execute is takes longer the first time. When I set next statement to run it again, it executes immediately. Is there a compile of the query the first time?
Because you are calling ToList in the first query and that causes fetching all records from DB and do the counting in memory. Instead of ToList you can just call Count() to get the same behaviour:
var count = (from I in db.mytable
where xyz
select I).Count();
You must not call .ToList() method, because you start retrieve all objects from database.
Just call .Count()
var count = (from I in db.mytable
where xyz
select I).Count();
Count can take a predicate. I'm not sure if it will speed up your code any but you can write the count as such.
var count = db.mytable.Count(x => predicate);
Where predicate is whatever you are testing for in your where clause.
Simple fiddling in LINQPad shows that this will generate similar, if not exactly the same, SQL as above. This is about the simplest way, in terseness of code, that I know how to do it.
If you need much higher speeds than what EF provides, yet stay in the confines of EF without using inline SQL you could make a stored procedure and call it from EF.

ServiceStack.OrmLite: Where is the method to write custom SQL and get result set back?

I have been reading on
https://github.com/ServiceStack/ServiceStack.OrmLite
to find methods so I can execute normal SQL (string commands), and get a result set back, but I dont think there is any.
I am testing OrmLite v 4.0.17.0.
On the page above, there is a method SqlList mentioned, but I have no such method available:
I have an ExecuteSql, but I get no result set back, just an int:
So, two questions:
Is there a way to execute custom queries, a method that takes in a string as parameter, and where I then get back a result set, rows or objects or something?
And while I am at it, how do I create a "LIMIT", for example "SELECT * FROM a LIMIT 10"?
Here is the version info:
Yeah I recently noticed that db.SqlList got lost in the OrmLite v4 refactor so I've restored it back in this commit. Which will be available in the next release of v4, before the end of the month.
You can still use db.Select for raw SELECT queries, e.g:
var results = db.Select<Poco>("SELECT * FROM a LIMIT 10");
It's only an issue when it's not a SELECT statement because we'd assume it's short-hand like:
var results = db.Select<Poco>("Foo = 'bar'");
And automatically add the rest of the SQL for you, but this is a problem when you're not issuing a SELECT statement, e.g. calling a stored procedure, which is what db.SqlList is for since the raw SQL remains untouched.
Support for LIMIT in Typed Expression API
Another way to query with a limit is to use the typed expression API, e.g:
var results = db.Select<Poco>(q => q.Limit(10));

How to call stored procedure in EF4

I'm trying to call a stored procedure in Entity Framework 4 application and so far getting strange results. Stored procedure takes IN and OUT parameters, and returns resultset. I mapped stored procedure and created a complex type that represents a row in returned resultset. I call it
using (MyObjectContext ctx = new MyObjectContext())
{
ObjectParameter out1 = new ObjectParameter("out1", typeof(String));
ObjectParameter out2 = new ObjectParameter("out2", typeof(String));
var res = ctx.my_proc(1,2, out1,out2);
}
The problem is that unless I call res.ToList() (or enumerate through res, or call any methods that accesses underlying collection), values of out1 and out2 are null.
How do I fix it?
Thanks
You cannot fix it. It is a gotcha. Result set must be materialized or thrown away before output parameters are accessible because these output parameters are transferred in the last result set so internal data reader must first read the returning result set with main data and then access the next result set to read output parameters. Btw. it is the same if you use ADO.NET directly - that is not a feature of Entity framework itself but the way how SQL server returns output parameters and the way how DataReader consumes result sets in sequential order.
when u call procedure or query that returns a table of rows
EF does real execution when user calls ToList or enumerate the return value

Categories

Resources