Lightswitch - C# LINQ Preprocess Query - c#

I'm pretty new to LINQ and I'm having trouble restricting the number of values (strings in "yyyy-mm" format) from my "Availabilities" entity which are shown on a Lightswitch screen, based on a Query ("LINQ_Query"). The idea is to show only "Availabilities" which are recent - for example where int.Parse(av.Availability.Substring(0,4)) > 2013
The reason I'm doing this is that "Availability" entity contains strings and not all of them are in "yyyy-MM" format - there are also entries like "Available", "Delayed", "2014" etc. I want to filter only the ones which have a length of 7 and ideally are more recent than 2013-12 and not in the future (Availability > current date).
In SQL I have achieved this with the following code:
SELECT Availability FROM Availabilities where LEN(Availability)=7 and LEFT(Availability,4) > 2013 and availability<=CONVERT(varchar(7),GETDATE(),126) order by Availability desc
The C# code I use for my PreprocessQuery is the following and it compiles with no errors:
partial void LINQ_Query_PreprocessQuery(ref IQueryable<Availabilities> query)
{
query = from av in query
where av.Availability.Length==7 && int.Parse(av.Availability.Substring(0,4)) > 2013
select av;
}
However, when I deploy and test there are the dreaded red Xs on the screen in question. I enabled tracing and I see the error is:
[Microsoft.LightSwitch.DataService][Application:Error][LightSwitchApplication.ApplicationData:LINQ_Query] An exception has occurred: Microsoft.LightSwitch.DataServiceOperationException: LINQ to Entities does not recognize the method 'Int32 Parse(System.String)' method, and this method cannot be translated into a store expression.
Is there a workaround for this? I was thinking of executing a separate "IDataServiceQueryable" query and then pointing the Preprocess IQueryable query to the results of the "IDataServiceQueryable" one. Is there any chance this or another type of query would work with int.Parse or DataTime.Parse/ParseExact?
Thanks in advance!
P.S. Some more details about my setup: I'm testing a Web Lightswitch 2011 application, hosted on my PC as IIS Server. The Database is hosted on a SQL Server 2008 Express x64 SP3 also on my PC, which leads me to anothe question - since LINQ to Entities doesn't support the functions I need, can I create a LINQ to SQL query on the Availabilities table?

Try splitting them up and removing the cast
partial void LINQ_Query_PreprocessQuery(ref IQueryable<Availabilities> query)
{
query = query.Where(x=>x.Availability.Length==7);
query = query.Where(x=>x.Availability.Substring(0,4) == "2013";
}
Ctype or Parse in Linq could be trouble (if it would fail for one, it fails for all)
If it works, join the 2 queries again.

Related

SQLite & LinQ Take function

I am using SQLite (install through Nuget Package Manager). I had been trying
to use Linq for Paging.
The error that I got: SQL logic errornear ".": syntax error'
The Sql query code at "tQuery" that I observed during debug is
{SELECT TOP (2) [t0].[R_IDs]......FROM [TTable].
The Top Keyword is not Supported in Sqllite, correct? It is suppose to be Limit and is at the end of of the Query Statement.
I had been searching around for answer.
Any one ever had this problem?
Table <T_Table> MyT = db.GetTable<T_Table>();
var tQuery = (from my_t in MyT
select my_t).Take(5);

string Text.ToUpper() slow inside of Linq query in C# Visual Studio 2017 ver 15.1.1

I have the following code that takes 5-8 seconds to complete:
recent_items returnedData = (from d in db.recent_items
where d.item_number == scannerInput.Text.ToUpper()
select d).FirstOrDefault();
Where as the following executes in less than a half second:
string search = scannerInput.Text.ToUpper();
recent_items returnedData = (from d in db.recent_items
where d.item_number == search
select d).FirstOrDefault();
What in the world is going on?
The most likely reason for the discrepancy is that EF evaluates the first condition in memory, after retrieving all rows from RDBMS.
Microsoft documentation says the following about Client vs. Server Evaluation:
Entity Framework Core supports parts of the query being evaluated on the client and parts of it being pushed to the database. It is up to the database provider to determine which parts of the query will be evaluated in the database.
Your EF DB provider could not send scannerInput.Text.ToUpper() to RDBMS for evaluation, so it did all comparisons in memory, after retrieving data rows from the database. This decision is correct, because EF DB provider cannot assume that consecutive evaluations of the above expression would yield identical results.
Second query, on the other hand, used a captured variable for the query. The value of that variable is guaranteed to stay constant while EF runs the query, so it proceeded to evaluating the request on the RDBMS side.

How do you display the SQL statement of a Linq-To-SQL query?

I'm trying to retrieve the earliest DateTime value that has a specific date.
The Holder instance has already been retrieved from the data context (without prefetching), now I need to search through the IO EntitySet (that has not been fetched).
I'm doing this in a foreach loop for each holder so it takes a long time to retrieve the requested values. Indexing the table didn't help so I want to see the SQL statement in order to optimize the database.
This is the code that needs to be translated into SQL:
DateTime? entryDateTime = (from io in Holder.IOs
where io.IOStatus == "Entry" &&
io.IODateTime.HasValue &&
io.IODateTime.Value.Date == date.Date
select io.IODateTime).Min();
I can't use LinqPad because the linq statement doesn't directly quesry the DataContext, but the IOs EntitySet.
Also, if anyone has an idea on how to rewrite the linq statement in order to speed up the retrievals, please let me know. I don't want to use LoadOptions as this would delay the app starting process.
Grab the query, stop on it in in the debugger. YOu should be able to see it with a mouse over on the query object.
I think your problem is the Min. You get in SQL what you have in LINQ, and this is not what I would do in SQL.
I would gl with an order by and a Top 1 - which translates into First () in LINQ.
You have several options. Use a profiler on your database.
http://msdn.microsoft.com/en-us/library/ms181091.aspx
or
Where can I get the old, free version of Anjlab's SQL Profiler?
Or coding: hack into the LINQ 2 SQL log:
http://damieng.com/blog/2008/07/30/linq-to-sql-log-to-debug-window-file-memory-or-multiple-writers

LINQ and selection rows from big database

I have some database ang now it contains a table with about 100 rows. But in future it will have not 100 but 1 000 000+ rows and I have to be careful with my web application I'm developing now.
Problem is next: at web page I need to create paged list what will show records to user. And here is a sample of code that I plan to use
public IQueryable<MyTable> GetRows(int from, int to)
{
var queryRes = (from row in SomeDataContext.MyTable
order by row.id
select row).AsQueriable();
return queryRes.Take(to).Skip(from);
}
It is only sample of code. I did not run it.
But question is what will go on in this case? I see tow scenarios
It will load all rows from database and at server side and records in range from 'from' to 'to' will be returned. Other will be ignored. In this case my application will have big troubles. Imagine load 1 000 000 rows from database every time. It will be disaster.
It will construct SQL request what will return only rows I need without loading others. That's exactly what I need.
I think that it will be 2 scenario but I'm not sure and can't check it. Am I correct?
As a side-note, you don't have to call AsQueryable. It is enough to do
var queryRes = SomeDataContext.MyTable.OrderBy(r => r.Id);
return queryRes.Take(to).Skip(from);
And to answer your question - scenario 2 will be executed. You can always check the generated SQL by using the SQL Server Profiler, but in case you are using Entity Framework, you can even do queryRes.ToString(). And as #Aron correctly pointed out - the query will be actually executed against the database only when enumerating the results (e.g. calling queryRes.ToList()).
These questions address the issue of looking up the SQL code in more detail:
How to view generated SQL from Entity Framework?
exact sql query executed by Entity Framework
Strictly speaking, neither 1 nor 2 is correct. Running the code DOES NOT hit the database. It constructs an expression tree. The calling code can still modify the expression tree further without hitting the database.
With the IQueryable interface no SQL is run. It is at the point when you call IEnumerable.GetEnumerator() that the underlying Linq Provider converts the WHOLE expression into a query. In this case a SQL query, and then run it.
So for example, with this code. You could have
void Main()
{
var foo = from x in GetRows(10, 10)
where x.Id > 1000
select x;
foreach(var f in foo)
{
//Stuff
}
}
The sql that is actually run will actually be closer to
SELECT a,b,c FROM
(SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number
FROM Table
WHERE id > 1000) t0
WHERE to.row_number BETWEEN 10 and 20;
To be honest you are going about this wrong. You don't need a GetRows method. I would directly call the Linq query when constructing the table itself. You should take a look at the IRepository pattern that MVC scaffolding uses.
Finally if this is meant to be called as a WebQuery for AJAX I would look at the two OData implementations in .net (WCF Data Services and WebAPI OData).
You are right.
The 2. scenario is what will happen. When the query is eventuallty exectuted.
I Would sugges to reverse the Take - Skip, so you start by Skip
queryRes.Skip(from).Take(to)
Debuggen this method will not make any calls to the database. It just returns the query - not the resualt.
If you want to test exactly what will happen, try download LinqPad - it is a great to for demystifying linq queries.

LINQ to SQL doesn't return data, but the generated SQL statement does

I have a LINQ to SQL query that when executed does not return any data. However, when I debug, I can take the generated SQL query, plug in the values for the variables, and run it in SQL Management Studio to get the record I'm expecting. I'm taking the values for the variables while in debug mode as well.
Has anyone experienced something like this before?
As requested, LINQ statement (edited table and column names):
var q1 = from rr in db.ABC
from rd in db.DEF
where rr.a == rd.b
where rr.c == rd.c
where rr.d.Equals(id)
where rr.c.Equals(anotherId)
select new
{
rr.d, rr.x, rr.a,
rr.y, rr.z, rr.v,
rr.e, rd.r
};
var r1 = q1.Single();
I'm using very similar queries in other places with success.
Run the SQL Server profile, take the EXACT query it's running (you shouldn't have to "plug in" any values), and run that.
Are you still obtaining results?
Is it plugging in the correct values?
Are you querying a nullable value?
Could you show us the code and generated query?
I would double check the connection string that LINQ to SQL is using. It might just be hitting the wrong database.
Have you run Profiler to make sure the values you think the stament is going to have are actually inthe statment that was sent to the server?

Categories

Resources