I have two tables in a one to many relationship. (products and qty break pricing). At the database level I cannot create a relationship between the two tables. I brought those two tables into LINQ and created the association manually.
I need to do a big LINQ query and have the tables be joined. My problem is it's not using a join to get the data. LINQ is using 1 select on the main table, then 1 select for each row in that main table.
Dim db As New LSSStyleDataContext(connString)
Dim options As New DataLoadOptions()
options.LoadWith(Function(c As commerce_product) c.commerce_qty_breaks)
db.LoadOptions = options
Dim dbProducts = (From prods In db.commerce_products).ToList
Any thoughts on why this might be? Thanks!
Paul
EDIT: here are the two tables:
CREATE TABLE [dbo].[commerce_product](
[pf_id] [int] NOT NULL,
[name] [varchar](500) COLLATE SQL_Latin1_General_CP1_CI_AS
[description] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[restricted] [varchar](5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_commerce_product_1] PRIMARY KEY NONCLUSTERED
(
[pf_id] ASC
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
And the other table:
CREATE TABLE [dbo].[commerce_qty_break](
[pf_id] [int] NOT NULL,
[sku] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[qty] [int] NOT NULL,
[list_price] [int] NOT NULL,
[break_id] [int] NOT NULL,
CONSTRAINT [PK_commerce_qty_break] PRIMARY KEY CLUSTERED
(
[pf_id] ASC,
[qty] ASC,
[break_id] ASC
) ON [PRIMARY]
) ON [PRIMARY]
The DBML is straight forward with only the two tables. I created an association between the two tables, "commerce_product" being the parent and "commerce_qty_break" being the child joined by "PF_ID".
I can write something like this:
Dim dbproducts = From prods In db.commerce_products _
Join qtys In db.commerce_qty_breaks On prods.pf_id Equals qtys.pf_id _
Select prods
And i see that it joins on the table in the query, but as soon as i try and spin through the "qty_breaks" it starts executing selects to get that info.
I'm totally stumped.
Edit 2: Here is the DBML:
<?xml version="1.0" encoding="utf-8"?>
<Database Name="LSScommerceDB_DevB" Class="LSSStyleDataContext" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
<Connection Mode="AppSettings" ConnectionString="***" SettingsObjectName="HSLPriceUpdate.My.MySettings" SettingsPropertyName="LSScommerceDB_DevBConnectionString" Provider="System.Data.SqlClient" />
<Table Name="dbo.commerce_product" Member="commerce_products">
<Type Name="commerce_product">
<Column Name="pf_id" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
<Column Name="name" Type="System.String" DbType="VarChar(500)" CanBeNull="true" />
<Column Name="description" Type="System.String" DbType="Text" CanBeNull="true" UpdateCheck="Never" />
<Column Name="list_price" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="image_file" Type="System.String" DbType="VarChar(255)" CanBeNull="true" />
<Column Name="image_width" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="image_height" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="sale_price" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="sale_start" Type="System.DateTime" DbType="DateTime" CanBeNull="true" />
<Column Name="sale_end" Type="System.DateTime" DbType="DateTime" CanBeNull="true" />
<Column Name="attr_label1" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
<Column Name="attr_label2" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
<Column Name="attr_label3" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
<Column Name="attr_label4" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
<Column Name="attr_label5" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
<Column Name="sku" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
<Column Name="UOM" Type="System.String" DbType="VarChar(50)" CanBeNull="true" />
<Column Name="Sell_Pack" Type="System.String" DbType="VarChar(50)" CanBeNull="true" />
<Column Name="mfg_model_number" Type="System.String" DbType="VarChar(50)" CanBeNull="true" />
<Column Name="mfg_id" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="logo_file" Type="System.String" DbType="VarChar(255)" CanBeNull="true" />
<Column Name="drop_ship" Type="System.String" DbType="VarChar(50)" CanBeNull="true" />
<Column Name="lead_time" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="hazard_flag" Type="System.String" DbType="VarChar(50)" CanBeNull="true" />
<Column Name="publish_date" Type="System.DateTime" DbType="DateTime" CanBeNull="true" />
<Column Name="restricted" Type="System.String" DbType="VarChar(5)" CanBeNull="true" />
<Association Name="commerce_product_commerce_qty_break" Member="commerce_qty_breaks" ThisKey="pf_id" OtherKey="pf_id" Type="commerce_qty_break" />
</Type>
</Table>
<Table Name="dbo.commerce_qty_break" Member="commerce_qty_breaks">
<Type Name="commerce_qty_break">
<Column Name="pf_id" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
<Column Name="sku" Type="System.String" DbType="VarChar(100) NOT NULL" CanBeNull="false" />
<Column Name="qty" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
<Column Name="list_price" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" />
<Column Name="sale_price" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="sale_start" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" />
<Column Name="sale_end" Type="System.DateTime" DbType="DateTime" CanBeNull="true" />
<Column Name="break_id" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
<Association Name="commerce_product_commerce_qty_break" Member="commerce_product" ThisKey="pf_id" OtherKey="pf_id" Type="commerce_product" IsForeignKey="true" />
</Type>
</Table>
</Database>
EDIT 3: Apparently this is only an issue in SQL 2000. SQL 2008 works fine. I have other tables that do eager loading in SQL 2000 and i can't figure out what the difference is between these two tables.
I created a VB console app and created the schema as you have it here.
Also - the relationship is PK -> PK so does this mean it's supposed to be a one-to-one relationship?
I populated the tables with a row each (see below) and ran the code you've listed above. I ran SQL Profiler and it only queried once:
SELECT [t0].[pf_id], [t0].[name], [t0].[description], [t0].[restricted],
[t1].[pf_id] AS [pf_id2], [t1].[sku], [t1].[qty], [t1].[list_price],
[t1].[break_id], (
SELECT COUNT(*)
FROM [dbo].[commerce_qty_break] AS [t2]
WHERE [t2].[pf_id] = [t0].[pf_id]
) AS [value]
FROM [dbo].[commerce_product] AS [t0]
LEFT OUTER JOIN [dbo].[commerce_qty_break] AS [t1] ON [t1].[pf_id] = [t0].[pf_id]
ORDER BY [t0].[pf_id], [t1].[qty], [t1].[break_id]
I wanted to make sure that the Data Options was forcing a deep load, so I added some extra code - here's the full code I used (and only the single query as above was traced):
Dim options As New DataLoadOptions()
options.LoadWith(Function(c As commerce_product) c.commerce_qty_breaks)
db.LoadOptions = options
Dim dbProducts = (From prods In db.commerce_products).ToList
Dim dbProduct = dbProducts.First().commerce_qty_breaks
Dim x = dbProduct.First().list_price
Here's the test data:
INSERT INTO [Test].[dbo].[commerce_product] ([pf_id],[name],[description],[restricted]) VALUES (1,'Test','Test','Test')
GO
INSERT INTO [Test].[dbo].[commerce_qty_break] ([pf_id],[sku],[qty],[list_price],[break_id]) VALUES (1,'22',1,1,1)
GO
hey, not sure i completely understood your question, but here's some info,
By default LINQ to SQL adopts lazy binding, meaning it won't query the database until it needs to. That's why you're getting multiple queries.
There are few things you can do to avoid multiple hits on the DB:
You can turn off lazy binding globally in the LINQ to SQL designer. But then you'll always perform JOINS if your tables have any relationships.
You do the JOIN manually in the LINQ query. If you do this, you'll have to specify which "fields" you want to return in your LINQ query to get back the JOINED data. And if you do this, then you'll be returning an Anonymous type
NOTE: LINQ to SQL doesn't support LEFT JOINS. If you google LINQ to SQL Left Joins you'll see plenty of info on this particular subject
cheers, and good luck!
Go grab LINQPad. It's great for playing with stuff like this.
Did you try something like this?
Dim dbproducts = From prods In db.commerce_products _
Join qtys In db.commerce_qty_breaks On prods.pf_id Equals qtys.pf_id _
Select new {prods, qtys}
I ended up using the entity framework and all is well.
Related
i have Banner and Group entities with xml configs
Banner.xml
<mapped-superclass name="Banner" table="luc_banners"
repository-class="BannerRepository">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="path" column="path" type="string" nullable="true" />
<field name="link" column="link" type="string" nullable="true" />
<field name="position" column="position" type="string" nullable="true" />
<field name="groupId" column="group_id" type="integer" />
<many-to-one field="group" target-entity="Group" inversed-by="banners">
<join-column name="group_id" referenced-column-name="id" nullable="false" on-delete="CASCADE" />
</many-to-one>
</mapped-superclass>
Group.xml
<mapped-superclass name="Group" table="luc_banners_groups" repository-class="GroupRepository">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" column="group_name" type="string" nullable="true" />
<field name="type" column="group_type" type="string" nullable="true" />
<field name="status" column="group_status" type="string" nullable="true" />
<field name="order" column="group_order" type="integer" nullable="true" />
<one-to-many field="banners" target-entity="Banners" mapped-by="group">
<cascade>
<cascade-all />
</cascade>
</one-to-many>
</mapped-superclass>
when trying to get banners form group object i get empty array, and Profiler shows this sql SELECT l0_.group_name AS group_name0, l0_.id AS id4 FROM luc_banners_groups l0_ WHERE l0_.group_status = ? and show not valid entity with this error Banner - The association Banner#group refers to the inverse side field Group#banners which does not exist.
Can you help me with this thing ?
remove <field name="groupId" column="group_id" type="integer" /> from Banner.xml, I think it's overriding the second one..
I'm using FOSUserBundle and I've created a Message table with two columns, that are relating to the User from FOSUserBundle.
I want to get messages and information about the author using one query.
Following schema.xml:
<?xml version="1.0" encoding="UTF-8"?>
<database name="default" namespace="Acme\StoreBundle\Model" defaultIdMethod="native">
<table name="message">
<column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
<column name="title" type="varchar" size="64" required="true" defaultValue="(untitled)"/>
<column name="content" type="longvarchar" />
<column name="author_id" type="integer" required="true" />
<foreign-key foreignTable="fos_user">
<reference local="author_id" foreign="id" />
</foreign-key>
<column name="recipient_id" type="integer" required="true" />
<foreign-key foreignTable="fos_user">
<reference local="recipient_id" foreign="id" />
</foreign-key>
</table>
</database>
I was trying many options, with no result.
When I try, what seems to be logical:
$messages = MessageQuery::create()
->join('Message.Authorid')
->findByRecipientId(1);
I get an error: "Unknown table or alias Message"
With:
->join('Authorid')
Error: "Unknown relation Authorid on the Acme\StoreBundle\Model\Message table"
What am I doing wrong?
Thank you for your help.
Ok, I found it out.
The schema for both author and recipient has to look like:
...
<column name="author_id" type="integer" required="true" />
<foreign-key foreignTable="fos_user" phpName="Author">
<reference local="author_id" foreign="id" />
</foreign-key>
<column name="recipient_id" type="integer" required="true" />
<foreign-key foreignTable="fos_user" phpName="Recipient">
<reference local="recipient_id" foreign="id" />
</foreign-key>
...
The important part is the phpName.
Now the controller. And here is something weird that happens, but it doesn't disturb.
$messages = MessageQuery::create()
->find();
return $this->render('AcmeStoreBundle:Message:index.html.twig',
array('messages' => $messages)
);
And after this easy code, I have access to everything from twig.
At this point I'd like to show an example:
When the controller looks like above, then
# AcmeStoreBundle:Message:index.html.twig
messages
Shows every field of the message table like:
Acme\StoreBundle\Model\Message_0: Id: 1 CreatedAt: !!php/object:O:8:"DateTime":3: {s:4:"date";s:19:"2013-03-20 13:00:00";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";} Title: (untitled) Content: 'test content' AuthorId: 1 RecipientId: 2 Acme\StoreBundle\Model\Message_1: Id: 2 CreatedAt: !!php/object:O:8:"DateTime":3:{s:4:"date";s:19:"2013-03-20 13:15:22";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";} Title: (untitled2) Content: 'bla bla content 2' AuthorId: 2 RecipientId: 1
As you can see, there is nothing about the relationship with author or recipient, but when I call message.author.username, or message.recipient.username (in the for loop of messages) I'm getting this. And this is what I actually expected.
And now when the controller looks like:
$messages = MessageQuery::create()
->joinWith('Author')
->find();
return $this->render('AcmeStoreBundle:Message:index.html.twig',
array('messages' => $messages)
);
messages (in twig) throws all the fields like above, and an author object (called author, not user, because of phpName from the schema).
Thank you guys for reading my question and many thx for participation.
The join method takes the relation using tables or phpName aliases, not the fields. So you probably want:
->join("Message.Author")
Or, as your foreign key suggests, maybe this?
->join("Message.FosUser")
UPDATE
With two FK references to the same table, you will want to use the phpName and refPhpName attributes of the foreign-key tag:
<table name="message">
...
<foreign-key foreignTable="fos_user" phpName="Author" refPhpName="AuthoredMessage">
<reference local="author_id" foreign="id" />
</foreign-key>
<foreign-key foreignTable="fos_user" phpName="Recipient" refPhpName="ReceivedMessage">
<reference local="recipient_id" foreign="id" />
</foreign-key>
</table>
Then you could try using ->join('Message.Author') or ->join('Message.Recipient')
See the documentation of the foreign-key element.
For some reason when I generate a change log with Liquibase it uses wrong precision. It generates a column with data type NUMBER(0,-127).
Does anybody know how to fix this?
<changeSet author="sfasdf (generated)" id="1357744702717-1">
<createTable schemaName="BLA" tableName="ADT_PAGE_ACCESS">
<column name="ID" type="NUMBER(0,-127)">
<constraints nullable="false" primaryKey="true" primaryKeyName="ADT_PAGE_ACCESS_PK" primaryKeyTablespace="ZON_IND1"/>
</column>
<column name="PAGE_ID" type="VARCHAR2(100 BYTE)">
<constraints nullable="false"/>
</column>
<column defaultValueComputed="sysdate" name="ACCESSED" type="DATE">
<constraints nullable="false"/>
</column>
<column name="CUSTOMER_ID" type="NUMBER(0,-127)"/>
<column name="USERID" type="VARCHAR2(25 BYTE)"/>
</createTable>
</changeSet>
Trying to persist an object results in this exception being thrown. It complains about an incorrect type but then expects that same type. The exception started appearing after renaming the project from dbd2012_p2 to dbd2012_p3 (it's a continuation from the previous assignment).
I have found no information on Google about this exception. I've gone through the metadata files making sure there are no instances of dbd2012_p2 left behind and I am now stumped.
Our database is basically a many-to-many relationship: Prova with Tag. Mesura models the relationship with a few extra attributes (activity, datetime, x, y and z coords).
Exception
javax.jdo.JDOUserException: The owner field prova of element class dbd2012_p3.Mesura has an incorrect type "dbd2012_p3.Prova". Should be "dbd2012_p3.Prova"
javax.jdo.JDOUserException: The owner field prova of element class dbd2012_p3.Mesura has an incorrect type "dbd2012_p3.Prova". Should be "dbd2012_p3.Prova"
at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:519)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:736)
at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:756)
...
at dbd2012_p3.dbd2012_p3.main(dbd2012_p3.java:28)
Code
for (String name : names) {
for (String seq : seqs) {
Prova prova = new Prova(name, seq);
pm.makePersistent(prova); // Exception thrown here
}
}
Prova.java
#PersistenceCapable
public class Prova {
#PrimaryKey //OJO
private String nom_persona = null;
#PrimaryKey
private String num_seq = null;
private Set tagRelations = new HashSet();
public Prova(String nou_nom_persona, String nou_num_seq) {
nom_persona = nou_nom_persona;
num_seq = nou_num_seq;
}
public Prova(){}
package-mysql.orm
This is how we have our tables defined:
<?xml version="1.0"?>
<!DOCTYPE orm SYSTEM "file:/javax/jdo/orm.dtd">
<orm>
<package name="dbd2012_p3">
<class name="Prova" type="application" table="prova">
<field name="nom_persona" primary-key="true">
<column name="nom_persona" length="45" jdbc-type="VARCHAR"/>
</field>
<field name="num_seq" primary-key="true">
<column name="num_seq" length="45" jdbc-type="VARCHAR"/>
</field>
<field name="tagRelations" persistence-modifier="persistent" mapped-by="prova">
<collection element-type="Mesura" />
</field>
</class>
<class name="Tag" type="application" table="tag">
<field name="codi" primary-key="true">
<column name="codi" length="45" jdbc-type="VARCHAR" />
</field>
<field name="nom">
<column name="nom" length="45" jdbc-type="VARCHAR" />
</field>
<field name="provaRelations" persistence-modifier="persistent" mapped-by="tag">
<collection element-type="Mesura" />
</field>
</class>
<class name="Mesura" type="datastore" table="mesura">
<field name="datetime" column="datetime"/>
<field name="prova" />
<field name="tag" />
<field name="activitat" />
<field name="x">
<column name="x" jdbc-type="DECIMAL" length="3" scale="1" />
</field>
<field name="y">
<column name="y" jdbc-type="DECIMAL" length="3" scale="1" />
</field>
<field name="z">
<column name="z" jdbc-type="DECIMAL" length="3" scale="1" />
</field>
</class>
</package>
</orm>
Note: I haven't tagged this as homework because the assignment is about applying data mining techniques to the data we add into the database. I can just rename the project back to its old name and it works again, but the exception is really bugging me.
Iam using LINQ To SQL with POCO's and XML mapping. I am getting the following error when I try to run the application: Cannot find type 'MyProject.DataTransfer.User' from mapping.
Below is the mapping:
<Table Name="Users" Member="User">
<Type Name= "MyProject.DataTrasnfer.User">
<Column Name="UserID" Member="UserID" DbType="Int NOT NULL IDENTITY" IsDbGenerated="true"
IsPrimaryKey="true"/>
<Column Name="UserName" Member="UserName" DbType="nvarchar(100) NOT NULL" />
<Column Name="Password" Member="Password" DbType="nvarchar(32)"/>
<Column Name="IsActive" Member="IsActive" DbType="bit NOT NULL"/>
<Column Name="InsertedBy" Member="InsertedBy" DbType="Int NOT NULL" />
<Column Name="InsertedDate" Member="InsertedDate" DbType="DateTime NOT NULL" />
<Column Name="UpdatedBy" Member="UpdatedBy" DbType="Int NOT NULL" />
<Column Name="UpdatedDate" Member="UpdatedDate" DbType="DateTime NOT NULL" />
<Column Name="Version" Member="Version" DbType="rowversion NOT NULL" IsDbGenerated="true"
IsVersion="true" AutoSync="Always"/>
</Type>
</Table>
But 'MyProject.DataTransfer.User' exists in the solution. What could be the possible reasons for this error?
Typo: MyProject.DataTrasnfer.User. You have transposed the s and the n.
I suppose that you have a class MyProject.DataTraSNfer.User in mapping and MyProject.DataTraNSfer.User in code. Misprint in post or in code?