Need help converting a Linq query (Silverlight RIA Entity - Oracle DB) - oracle

I have no problem with SQL, but I'm finding Linq a little confusing.
C#, .NET4, Silverlight, RIA services, Oracle DB (v?), VS2010 running Devart dotConnect 6.10.121.
I have a RIA Entity
public sealed partial class ProcessLogHdr : Entity
{
DateTime JobDate;
string InterfaceName;
int SuccessfulCount;
int FailCount;
int TotalCount;
}
There are more fields such as user, etc, that won't be applicable to this post.
There are many jobs that make up a process. Each job has an entry in this table, but the view I want is a date group by summary.
I will be calling context.Load on a query, where I pass in the start and end date, which in Oracle looks like this:
select
trunc(JobDate),
InterfaceName,
sum(SuccessfulCount) as Total_Pass,
sum(FailCount) as Total_Fail,
sum(TotalCount) as Total,
max(JobDate) as Last_Msg_Processed_At_DT
from
ProcessLogHdrsEntity
where
JobDate >= START_DATE_IN_VAR and
JobDate <= END_DATE_IN_VAR
group by
trunc(JobDate),
InterfaceName
order by
trunc(JobDate) desc,
InterfaceName asc;
conttext.Load will call the linq query from a method that returns IQueryable.
The linq statement must run for Oracle under Devart dotConnect for Oracle.
I'm guessing I need some custom class to hold the results, like ProcessLogHdrDateSummary.
If you guys could help me fill in the missing ????? linq, I would be so grateful:
public IQueryable<ProcessLogHdrDateSummary> GetProcessLogHdrsDateSummary(DateTime START_DATE_IN_VAR, DateTime END_DATE_IN_VAR)
{
return ?????
}
Many Thanks!

There's no simple answer to this. One of the characteristics of LINQ to database providers is that some queries execute immediately, while others don't. Aggregation functions (MAX, MIN, etc) return immediately. So do some LINQ functions that specify particular output, such as .First(). Anything returning a collection will likely not execute immediately, and will return an IQueryable<> of some type.
What type? That depends on what the select clause of the LINQ statement specifies (which is not the same as the generated SQL select clause). "from c in db.customers select c" returns customer objects, but you can also use the select clause to populate other classes, or anonymous classes.
If a LINQ query returns an IQueryable<>, remember that the query hasn't executed yet! It won't execute until you start processing the data. You must process the data while still in scope of the data context, because once that's gone, you've lost your database connection.
You can always force an IQueryable<> to execute by ending it with .ToList(), .ToArray(), .ToDictionary(), or a few others. The List<> will use the same generic type as the IQueryable<> and the select clause (or .Select() method) of the LINQ statement.

The LINQ query will be rather complicated. I recommend that you follow these steps:
1. Create a stored procedure with an out cursor:
CREATE PROCEDURE myQuery(
DATE START_DATE_IN_VAR,
DATE END_DATE_IN_VAR,
cur out sys_refcursor) AS
BEGIN
OPEN cur FOR SELECT
trunc(JobDate),
InterfaceName,
sum(SuccessfulCount) as Total_Pass,
sum(FailCount) as Total_Fail,
sum(TotalCount) as Total,
max(JobDate) as Last_Msg_Processed_At_DT
from
ProcessLogHdrsEntity
where
JobDate >= START_DATE_IN_VAR and JobDate <= END_DATE_IN_VAR
group by
trunc(JobDate), InterfaceName
order by
trunc(JobDate) desc, InterfaceName asc;
END;
2. Add this procedure to the model. If you are using Devart Entity model, the return type will probably be generated. In other case you will need to create an entity or a complex type that will represent the return type of the generated method.
3. Treat the method call as a usual DomainService method.

Related

Oracle not using index, Entity Framework & Devart DotConnect for oracle

The table in question has ~30mio records. Using Entity Framework I write a LINQ Query like this:
dbContext.MyTable.FirstOrDefault(t => t.Col3 == "BQJCRHHNABKAKU-KBQPJGBKSA-N");
Devart DotConnect for Oracle generates this:
SELECT
Extent1.COL1,
Extent1.COL2,
Extent1.COL3
FROM MY_TABLE Extent1
WHERE (Extent1.COL3 = :p__linq__0) OR ((Extent1.COL3 IS NULL) AND (:p__linq__0 IS NULL))
FETCH FIRST 1 ROWS ONLY
The query takes about four minutes, obviously a full table scan.
However, handcrafting this SQL:
SELECT
Extent1.COL1,
Extent1.COL2,
Extent1.COL3
FROM MY_TABLE Extent1
WHERE Extent1.COL3 = :p__linq__0
FETCH FIRST 1 ROWS ONLY
returns the expected match in 200ms.
Question: Why is it so? I would expect the query optimizer to note that the right part is false if the parameter is not null, so why doesn't the first query hit the index?
Please set UseCSharpNullComparisonBehavior=false explicitly:
var config = Devart.Data.Oracle.Entity.Configuration.OracleEntityProviderConfig.Instance;
config.QueryOptions.UseCSharpNullComparisonBehavior = false;
If this doesn't help, send us a small test project with the corresponding DDL script so that we can investigate the issue.

Oracle IN clause with tuples using NHibernate components

I've declared some entity (named Employee) with FluentNHibernate mapping using CompositeId and ComponentCompositeIdentifier. My component identifier (named Person) consists of two fields:
LastName
FirstName.
When I look for employees using single person, everything works great. I need to look for employees by list of persons:
var result = from em in Session.Query<Employee>() where persons.Contains(em.Person)
Is NHibernate able to generate some sort of tuple expressions, like that? I'm using Oracle database.
SELECT * FROM Employees WHERE (FirstName, LastName) IN (('Guy', 'Himuro'), ('Karen', 'Colmenares'));
It's very likely you need https://github.com/nhibernate/nhibernate-core/pull/2159 to make it work. So currently it's not supported in NHibernate 5.2.

Pl/SQL query a view in function

I have the function below
CREATE OR REPLACE FUNCTION BUTCE_REPORT_Fun (birim_id IN VARCHAR2)
RETURN sys_refcursor
IS
retval sys_refcursor;
BEGIN
OPEN retval FOR
select *
from ifsapp.butce_gerceklesme
WHERE budget_year = '2018'
AND USER_GROUP = birim_id ;
RETURN retval;
END BUTCE_REPORT_Fun;
and am trying to execute the function this way
SELECT * from table(IFSAPP.BUTCE_REPORT_FUN('3008'))
the line above generates this exception
ora-22905 cannot access rows from a non-nested table item
to keep in mind that ifsapp.butce_gerceklesme is a view (which I do not think that it matters).
So how I can solve this. any help is appreciated.
Actually, am trying to create a function that returns rows from the view above according to the parameters provided. so if I can achieve that in another way that would be better.
Ref Cursors are for use in program calls: they map to JDBC or ODBC ResultSet classes. They can't be used as an input to a table() call. Besides, there is no value in calling your function in SQL because you can simply execute the embedded query in SQL.
the main table is huge and the inner query assigned to USER_GROUP is selected every time
So maybe what you want is subquery factoring AKA the WITH clause?
with ug as (
select con2.CODE_PART_VALUE
from IFSAPP.ACCOUNTING_ATTRIBUTE_CON2 con2
where COMPANY = 'XYZ'
and ATTRIBUTE = 'ABC'
and CODE_PART = 'J'
and con2.ATTRIBUTE_VALUE=407
AND rownum = 1
)
select *
from ifsapp.butce_gerceklesme t
join ug on t.USER_GROUP = ug.CODE_PART_VALUE
WHERE t.budget_year = '2018'
Tuning queries on StackOverflow is a mug's game, because there are so many things which might be responsible for sub-optimal performance. But as a rule of thumb you should try to tune the whole query. Encapsulating a part of it in PL/SQL is unlikely to improve response times, and indeed may degrade them.

Symfony3 multiple update with subquery

Is there ability to make a multiple update with subquery on Symfony3 with Doctrine query builder or DQL?
For example, I want to run this query:
UPDATE tableA
SET fieldA2 = max_field2
FROM (SELECT
field1,
max(field2) AS max_field2
FROM table
GROUP BY field1) AS subquery
WHERE subquery.field1 = tableA.field1;
I can't understand how to use $entityManager->createQuery()->update with FROM subquery.
As far as I know, it's not possible through DQL.
You need to go through a loop.
foreach($entities as entity)
{
$em->flush();
}
Else, you will consider Batch processing, or just use plain SQL. So it might be usefull to check DBAL.

Adding a random Guid column to a Linq to Entities query to grab random records

I've found some articles about using the RandomView view and the GetNewID function to pull back randomized records, but they are using this method with Linq to SQL which allows Functions and Stored Procs to be used with no return value or a scalar return value. From what I understand, a Stored Proc has to been returned as one of the Entity Framework objects from my generated model. I have been able to get that to work as an object, but not returning a scalar or no return set.
What I want to do is to simply add a column to my Linq query that contains a newly generated Guid so that I can order by the new Guids and take a specific number of records randomly. Can anyone help with some sort of lambda expression or join that would enable me to do this? It seems like it should be something built into EF, but I understand that we are on EF v1.
(Please provide code in VB.net)
In the Select clause of your Linq query, you should be able to insert a GUID like this:
var result = from myRecord in myTable
select new {
field1 = myRecord.field1,
field2 = myRecord.field2,
guidField = Guid.NewGuid()
};
Well, my VB is a little rusty, but I think this will work...
Dim result =
From myRecord in myTable _
Select field1, _
field2, _
guidField = System.Guid.NewGuid()

Resources