I'm using EF 6 beta1. I have a simple stored proc that returns two result sets:
ALTER PROCEDURE GetItemsByParentId
#parentID int
SELECT * FROM Table1 WHERE ParentID = #parentID
SELECT * FROM Table2 WHERE ParentID = #parentID
I want to call that stored proc using my ObjectContext. I'm using database first and I have an edmx, but I don't want to import the stored proc as a function if I don't have to.
I created two simple classes Table1DTO and Table2DTO to store the results of the stored proc. For the first result set I call this:
var result1 = ExecuteStoreQueryAsync< Table1DTO >("EXEC GetItemsByParentId #parentID", new SqlParameter("parentID", parentID));
List table1DTOList = result1.ToList();
That works fine. Then for the second result set I'm trying this:
var result2 = result.GetNextResult< Table2DTO >();
List improvementDetailInfos = result2.ToList();
The problem is result2 is coming back as null. What am I missing?
This may sound like splitting hairs, but Entity Framework supports multiple result sets. The problem is that the Entity Framework Tooling does not. This has been an issue since EF 4.1/4.2. So you have three options (that I can think of):
split up your calls to only use single result sets
use an alternate technology (dapper?) for the few critical stored procedures that require multiple result sets
manually edit the EDMX to create a multi-result set mapping for GetItemsByParentId
To be honest I've wrestled with this in a number of scenarios and none of the options are great. If you're something of a masochist, I wrote up an example and answered a question on how to edit the EDMX for multiple result sets.
Related
Im currently using jOOQ to build my SQL (with code generation via the mvn plugin).
Executing the created query is not done by jOOQ though (Using vert.X SqlClient for that).
Lets say I want to select all columns of two tables which share some identical column names. E.g. UserAccount(id,name,...) and Product(id,name,...). When executing the following code
val userTable = USER_ACCOUNT.`as`("u")
val productTable = PRODUCT.`as`("p")
create().select().from(userTable).join(productTable).on(userTable.ID.eq(productTable.AUTHOR_ID))
the build method query.getSQL(ParamType.NAMED) returns me a query like
SELECT "u"."id", "u"."name", ..., "p"."id", "p"."name", ... FROM ...
The problem here is, the resultset will contain the column id and name twice without the prefix "u." or "p.", so I can't map/parse it correctly.
Is there a way how I can say to jOOQ to alias these columns like the following without any further manual efforts ?
SELECT "u"."id" AS "u.id", "u"."name" AS "u.name", ..., "p"."id" AS "p.id", "p"."name" AS "p.name" ...
Im using the holy Postgres Database :)
EDIT: Current approach would be sth like
val productFields = productTable.fields().map { it.`as`(name("p.${it.name}")) }
val userFields = userTable.fields().map { it.`as`(name("p.${it.name}")) }
create().select(productFields,userFields,...)...
This feels really hacky though
How to correctly dereference tables from records
You should always use the column references that you passed to the query to dereference values from records in your result. If you didn't pass column references explicitly, then the ones from your generated table via Table.fields() are used.
In your code, that would correspond to:
userTable.NAME
productTable.NAME
So, in a resulting record, do this:
val rec = ...
rec[userTable.NAME]
rec[productTable.NAME]
Using Record.into(Table)
Since you seem to be projecting all the columns (do you really need all of them?) to the generated POJO classes, you can still do this intermediary step if you want:
val rec = ...
val userAccount: UserAccount = rec.into(userTable).into(UserAccount::class.java)
val product: Product = rec.into(productTable).into(Product::class.java)
Because the generated table has all the necessary meta data, it can decide which columns belong to it, and which ones don't. The POJO doesn't have this meta information, which is why it can't disambiguate the duplicate column names.
Using nested records
You can always use nested records directly in SQL as well in order to produce one of these 2 types:
Record2<Record[N], Record[N]> (e.g. using DSL.row(table.fields()))
Record2<UserAccountRecord, ProductRecord> (e.g using DSL.row(table.fields()).mapping(...), or starting from jOOQ 3.17 directly using a Table<R> as a SelectField<R>)
The second jOOQ 3.17 solution would look like this:
// Using an implicit join here, for convenience
create().select(productTable.userAccount(), productTable)
.from(productTable)
.fetch();
The above is using implicit joins, for additional convenience
Auto aliasing all columns
There are a ton of flavours that users could like to have when "auto-aliasing" columns in SQL. Any solution offered by jOOQ would be no better than the one you've already found, so if you still want to auto-alias all columns, then just do what you did.
But usually, the desire to auto-alias is a derived feature request from a misunderstanding of what's the best approch to do something in jOOQ (see above options), so ideally, you don't follow down the auto-aliasing road.
This is a very weird problem
In short
var q = (some query).Count();
Gives my a number and
var q = (some query).ToList().Count();
Gives me entirely different number...
with mentioning that (some query) has two includes (joins)
is there a sane explanation for that???
EDIT: here is my query
var q = db.membership_renewals.Include(i => i.member).Include(i => i.sport).Where(w => w.isDeleted == false).Count();
this gives me a wrong number
and this:
var q = db.membership_renewals.Include(i => i.member).Include(i => i.sport).Where(w => w.isDeleted == false).ToList().Count();
Gives me accurate number..
EDIT 2
Wher I wrote my query as linq query it worked perfectly...
var q1 = (from d in db.membership_renewals where d.isDeleted == false join m in db.members on d.mr_memberId equals m.m_id join s in db.sports on d.mr_sportId equals s.s_id select d.mr_id).Count();
I think the problem that entity framework doesn't execute the joins in the original query but forced to execute them in (ToList())...
I Finally figured out what's going on...
The database tables are not linked together in the database (there are no relationship or constraints defined in the database itself) so the code doesn't execute the (inner join) part.
However my classes on the other hand are well written so when I perform (ToList()) it automatically ignores the unbound rows...
And when I wrote the linq query defining the relation ship keys (primary and foreign) it worked alright because now the database understands my relation between tables...
Thanks everyone you've been great....
My guess is IQueryable gives a smaller number cause not all the objects are loaded, kind of like a stream in Java, but IQueryable.toList().count() forces the Iqueryable to load all the data and it is traversed by the list constructor and stored in the list so IQueryable.toList().Count() is the accurate answer. This is based on 5 minutes of search on MSDN.
The idea is the underlying datastore of the IQueryable is a database iterator so it executes differently every time because it executes the query again on the database, so if you call it twice against the same table, and the data has changed you get different results. This is called delayed execution. But when you say IQueryable.ToList() you force the iterator to do the whole iteration once and dump the results in a list which is constant
Calling .ToString() to a IQueryable will return the generated SQL query with the values of the variables not plugged in yet. So there are these p__linq__n with n=0, 1, 2... in the query itself.
eg: SELECT * FROM foo WHERE x = p__linq__0
Question: Is it possible to get the final query? with the values of these variables already plugged into the query?
eg: SELECT * FROM foo WHERE x = 6
EF parametrizes queries to avoid Sql injections attacks and to be able to cache and re-use the same query even if some values change. To see parameters you can use the logging feature introduced in EF6. See this blogpost series for more details.
New to EF... using 6.0. I've have a Stored Proc which has the dynamic build select query inside a string variable that outputs using Execute(#StringQuery). This select has around 20 columns.
After adding this SP in EF, the return type is INT (not sure why). But I think I've to add all the columns manually in Complex types in EDMX. Wanted to know whether there is any better way to handle this as the columns are in huge number.
Please suggest.
Procedure Text:
DECLARE #StringQuery VARCHAR(MAX)
SET #StringQuery = 'SELECT AROUND 20 COLUMNS WITH LOT OF CONDITIONS ADDED'
EXECUTE(#StringQuery)
Open your model
Go to View->Other Windows->Entity Data Model Browser
In browser expand your Model->Function Imports and double click on Stored Proc
In Returns a Collections off choose Complex and press Get Column Information
Click Create New Complex Type
OK, Save
THere is a oracle query that I am trying to recreate using OpenJPA. I am writing a service in Websphere integration developer, and I am using OpenJPA as my ORM tool of choice. Previously this query was performed using a stored proc, a ref cursor was used and the information was retrieved like that. Now we are trying to use OpenJPA as our tool of choice. So I am thinking that I should then reconstruct the stored proc using OpenJPA...
SELECT DISTINCT
P.col1 as ID,
P.col2,
P.col3,
P.col4,
P.col5,
S.col6,
PC.col7,
P.col8,
A.ADDRESS_1,
A.ADDRESS_2,
A.ADDRESS_3,
A.CITY,
A.COUNTY,
A.STATE,
A.ZIP_CODE,
P.CONFIRMED_BY,
P.CONFIRMED_DATE,
P.MOD_USERID,
P.MOD_DATE
FROM EPCD13.PROVIDER P, EPCD13.provider_channel PC, EPCD13.provider_channel_link pcl,
EPCD13.provider_specialty ps, EPCD13.SPECIALTY S, EPCD13.Address A, EPCD13.ADDRESS_LINK AL
WHERE P.RESOURCE_ID = personID
AND P.RESOURCE_ID = PS.RESOURCE_ID (+)
AND 1 = PS.PRIMARY_SPECIALTY_ID (+)
AND PS.SPECIALTY_ID = S.SPECIALTY_ID (+)
AND P.RESOURCE_ID = PCL.RESOURCE_ID (+)
AND PCL.PROVIDER_CHANNEL_ID = PC.PROVIDER_CHANNEL_ID
AND 1 = PCL.PREFERENCE (+)
AND 9 = pc.channel_type_id (+)
AND PC.CHANNEL_ADDRESS NOT LIKE '%#%'
AND P.RESOURCE_ID = AL.RESOURCE_ID (+)
AND AL.ADDRESS_ID = A.ADDRESS_ID (+)
AND 1 = A.ADDRESS_TYPE_ID (+)
AND 1 = AL.PREFERENCE (+);
Notice all those inner Joins and so forth. I am thinking right now of putting a named query in one my methods that will return the same results as above. As you may note, there are multiple tables that are being called there and joined at various points... I am thinking I can just put this query into the createNamedQuery() function with minor changes... But I am thinking there has to be a simpler way to do this? Maybe not. Can I just call a stored proc using JPA?
Because your SQL is very complex it's not easy to convert to JPQL, I suggest preserve it.
You can use OpenJPA's NativeQuery, which can do SQL query. If your SQL is not started with SELECT, it will be treated as stored proc.
You can create a JPA entity for each table and then join the entities by doing something similar to this:
http://openjpa.apache.org/builds/1.1.1-SNAPSHOT/docs/jpa_overview_mapping_full.html
Look at the #OnetoMany and #ManytoOne and #ManytoMany annotations in the example for some ideas.