SQLite & LinQ Take function - c#

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);

Related

Select distinct on DocumentDB and C#

I am having a challenge retrieving data from my DocumentDB using C#.
I get the expected results when I run the query below in my Azure DocumentDB data explorer. Ignore the use of contains query, it's a dynamically crafted query
select distinct c.model from c where ( CONTAINS (c.manufacturer, \"BMW\") )
Attempting to run the same query on c# gives me an error
var dblink = UriFactory.CreateDocumentCollectionUri(ConfigurationManager.AppSettings["DocumentDbDatabase"], "Conversation");
var models = _dbclient.CreateDocumentQuery<dynamic>(dblink, "select distinct c.model from c where ( CONTAINS (c.manufacturer, "BMW") )").ToList();
The error I get is incorrect syntax near distinct
Where is the error emanating from?
You may want to upgrade to the latest .Net SDK (v1.22.0).
The syntax error here is from the SDK rather than the query service, given that support for DISTINCT was added recently. Upgrading to the latest SDK should fix the issue.

Expression Tree for .NET DateTime <> Oracle Timestamp like search

I need to know whether I can get a clue or not.
I am trying to build an Expression Tree that is evaluated via Entity Framework 6 (LINQ to Entities) via ODP.NET managed driver (current Version) to the appropriate Oracle statement in order to perform filtering. This works perfectly for string <> nvarchar2 datatypes. The output for a Contains search is something like:
Select *
[...]
FROM "MYSCHEMA"."MYTABLE" "Extent1"
WHERE ("Extent1"."ANVARCHAR2COLUM" LIKE '%givenStrValueToFind%')
Now I want to get the same result for a DateTime <> Timestamp(6) since this line of sql statement is valid for an oracle query and returns all Dates which contains '08':
select * from "MYSCHEMA"."MYTABLE" where ATIMESTAMP6COLUMN like '%08%';
Since I am new to Expression Trees, I first need to know (after googling alot and tried this an that), whether this is possible before I dig deeper into. And if so, how could this be accomplished best? Since there is no Contains Method defined for DateTime and DateTime? Maybe providing Extension methods? And I dont want to execude queries directly against database.
Any hints would be nice to 'unhook' the given database datatype perhaps...
Thx.
For EF 6 you can use :
ctx.MYTABLE.Where(x=>x.ATIMESTAMP6COLUMN.ToString().Contains("08")).ToList();
which translates to
SELECT
[Extent1].[some property name] AS [some property name],
[Extent1].[ATIMESTAMP6COLUMN] AS [ATIMESTAMP6COLUMN],
.
.
.
FROM [dbo].[MYTABLE] AS [Extent1]
WHERE CAST( [Extent1].[ATIMESTAMP6COLUMN] AS nvarchar(max)) LIKE N'%08%'
As far as what I know all versions of EF does not support string functions but EF 6.x supports this kind of functions(The EF that I tested with is EF 6.1.3, the test is done with sql server localdb as DBMS).
I don't know if I understood. Anyway, you don't need to build an expression tree to avoid DB load in memory. LINQ build an expression tree from an expression, EF translates the expression tree to a SQL statement (using the EF Provider) then the query is run on the DB.
In your case the LINQ Query should be something like this
myContext.MYTABLE.Where(e => e.ATIMESTAMP6COLUMN.Contains("08").ToList();
EDIT
Conversions:
You can use .ToString(). It should be a canonical function (function available on every EF Provider).
Other DateTime related functions:
You could have a look to other canonical functions (there are some about dates that allow to retrieve date parts) and also to non canonical functions (functions implemented only in EF Provider for oracle).
References:
Canonical functions https://msdn.microsoft.com/en-us/library/vstudio/bb738626(v=vs.100).aspx
Actually I can't find non canonical functions for Oracle.
If you need it the best thing is that you ask another question.

Lightswitch - C# LINQ Preprocess Query

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.

LINQ: Translating a SQL WITH clause to LINQ and Entity Framework

I have an app using Entity Framework. I want to add a tree view listing products, grouped by their categories. I have an old SQL query that will grab all of the products and categories and arrange them into parent nodes and children. I am trying to translate it into LINQ that uses the EF. But the SQL has a WITH sub-query that I am not familiar with using. I have tried using Linqer and LinqPad to sort it out, but they choke on the WITH clause and I am not sure how to fix it. Is this sort of thing possible in LINQ?
Here is the query:
declare #id int
set #id=0
WITH ChildIDs(id,parentid,type,ChildLevel) AS
(
SELECT id,parentid,type,0 AS ChildLevel
FROM dbo.brooks_product
WHERE id = #id
UNION ALL
SELECT e.id,e.parentid,e.type,ChildLevel + 1
FROM dbo.brooks_product AS e
INNER JOIN ChildIDs AS d
ON e.parentid = d.id
WHERE showitem='yes' AND tribflag=1
)
SELECT ID,parentid,type,ChildLevel
FROM ChildIDs
WHERE type in('product','productchild','productgroup','menu')
ORDER BY ChildLevel, type
OPTION (MAXRECURSION 10);
When I run the query, I get data that looks like this (a few thousand rows, truncated here):
ID.....parentid.....type.....ChildLevel
35429..0............menu.....1
49205..0............menu.....1
49206..49205........menu.....2
169999.49206........product..3
160531.169999.......productchild..4
and so on.
The WITH block is a Common Table Expression, and in this case is used to create a recursive query.
This will be VERY difficult in Linq as Linq doesn't play well with recursion. If you need all of the data on one result set that a Stored Procedure would be easier. Another option is to do the recursion in C# (not in Linq but a recursive function) and do multiple round-trips. The performance will not be as good but if you result set is small it may not make much difference (and you will get a better object model).
You may be able to solve this using LINQ to Entities, but it is non-trivial and I suspect it will be very time consuming.
In situations like this, you may prefer to build a SQL View or Table-Valued Function that returns the results for which you're looking. Then import that View or Table-Valued Function into your EF model and you can pull data directly from it using LINQ.
Querying the View in LINQ is no different than querying a table.
To get data from a Table-Valued Function in LINQ, you pass the function's parameters in after the name of the function, like so:
var query = from tvf in _db.MyTableValuedFunction(parameters)
select tvf;
EDIT
As suggested by #thepirat000, Table-Valued Function support is not available in Entity Framework versions prior to version 5. In order to use this functionality, EF must be running with .NET 4.5 or higher.
At the end of the day, I could not get this to work. I ended up writing out a SQL query dynamically and sending that straight to the database. It works fine, and I am not relying on any direct user input so there is no chance of SQL injection. But it seems so old school! For the rest of my program I am using EF and LINQ.
Thanks for the replies!

Linq query nhibernate; not supported exception

I'm fairly new to nHibernate having come from an EF background and I'm struggling with the following query :
_patientSearchResultModel = (from patient in _patientRepository.Query(patientSearch.BuildPatientSpecification())
join admission in _admissionRepository.Query(patientSearch.BuildAdmissionSpecification())
on patient.Id equals admission.Patient.Id
orderby admission.AdmissionDate
select new PatientSearchResultModel(patient.Id,
admission.Id,
false,
_phaseTypeMapper.GetPhaseTypeModel(admission.PhaseType),
patient.Last, patient.First,
admission.InPatientLocation,
admission.AdmissionDate,
admission.DischargeDate,
admission.RRI,
null,
admission.CompletionStatus,
admission.FollowupStatus)).ToList();
The intent of this query is to allow users to filter the two queries on parameters built up using the two Build???Specification functions and return the resultset. There could be many admission records and I would only like one PatientSearchResultModel per patient object, with the admission object being the newest one by Admission Date.
These objects are coming from nHibernate and it keeps return a Not Supported exception. There is also an association between Patient and Admissions thus : Patient.Admissions but i couldn't figure out how to then add the query filters return from the function Build???Specifications.
I'd be really grateful if someone could point me in the right direction; am I up against the Linq provider implementation here in nHibernate and need to move to Criteria or is it my Linq query ?
If anyone has any links or suggestions for good books or other learning materials in this area that would also be really helpful too.
I see several potential problems:
If you're using NHibernate 2.x + Linq2NHibernate explicit joins like that are not supported; in other versions they're just considered a smell.
I dont think NHibernate supports calling parameterized constructors in select clauses
I'm very sure NHibernate does not support calling instance methods in the select lambda
I'd suggest using the lambda syntax and SelectMany to alleviate potential join issues. Points #2 & #3 can be solved by projecting into an anonymous type, calling AsEnumerable then projecting into your model type.
Overall I'd suggest restructuring your code like:
var patientSpec = patientSearch.BuildPatientSpecification();
var admissionSpec = patientSearch.BuildAdmissionSpecification();
_patientSearchResultModel = _patientRepository.Where(patientSpec)
.SelectMany(p=>p.Admissions).Where(admissionSpec)
.Select(a=> new {
PatientId = a.Patient.Id,
AdminssionId = a.Id,
a.PhaseType,
a.Patient.Last,
a.Patient.First,
a.InPatientLocation,
a.AdmissionDate,
a.DischargeDate,
a.RRI,
a.CompletionStatus,
a.FollowupStatus
}).AsEnumerable()
.Select(x=> new PatientSearchResultModel(x.PatientId, x.AdmissionId ...))
.ToList();
Divide your query into parts and check which part runs and which doesn't.
My take on this is that select new ... is not supported in Linq to nHibernate.
I would recomend using something else, because it is simply too imature and feature-less to use seriously.
As with most popular LINQ-to-Database query providers, NHibernate will try to translate the whole query into a SQL statement to run against the database. This requires that all elements of your query are possible to express in the SQL flavour you're using.
In your query, the select new statement cannot be expressed in SQL, because you're making a call to the constructor of your PatientSearchResultModel class and are making a call to a GetPhaseTypeModel method.
You should restructure your query to express what you want to execute on the SQL database, then call AsEnumerable() to force the remainder of the query to be evaluated in-memory. After that call, you can call the constructor of your class and any .NET methods, and they will be executed as native code.
This query is too complex to describe it using Linq. It would give wrong result finally (if Patient has more than one admission records, result would have duplicate entries).
I see two steps for solution:
1) At development stage, use in-memory query. So, take Patients using ToList() first (query db at this moment). Some predicates (Patient filter like MRN, First, Last) could be used at this stage.
And then do search in-memory. Not performance, but working solution. Mark it for refactor to optimize later.
2) Finally, use NHibernate IQuery (ISQLQuery) and build sql query manually to make sure it would work as expected and work fast enough on SQL Server side. This is just read-only query and do not require Nhibernate query engine (Linq to Nhibernate) at all.

Categories

Resources