2 votes

LINQ to SQL : jointure interne avec association manuelle sur SQL 2000

J'ai deux tables dans une relation de type un à plusieurs. (produits et prix de rupture de qté). Au niveau de la base de données, je ne peux pas créer de relation entre les deux tables. J'ai amené ces deux tables dans LINQ et créé l'association manuellement.

Je dois faire une grosse requête LINQ et faire en sorte que les tables soient jointes. Mon problème est qu'il n'utilise pas de jointure pour obtenir les données. LINQ utilise une sélection sur la table principale, puis une sélection pour chaque ligne de cette table principale.

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

Vous avez une idée de la raison pour laquelle cela pourrait être le cas ? Merci ! Paul

EDIT : voici les deux tableaux :

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]

Et l'autre 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]

Le DBML est simple avec seulement les deux tables. J'ai créé une association entre les deux tables, "commerce_product" étant le parent et "commerce_qty_break" étant l'enfant joint par "PF_ID".

Je peux écrire quelque chose comme ça :

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

Et je vois qu'il joint la table dans la requête, mais dès que j'essaie de passer par les "qty_breaks", il commence à exécuter des sélections pour obtenir cette information.

Je suis totalement déconcerté.

Edit 2 : Voici le 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 : Apparemment, ce problème ne concerne que SQL 2000. SQL 2008 fonctionne bien. J'ai d'autres tables qui se chargent avec empressement dans SQL 2000 et je n'arrive pas à comprendre quelle est la différence entre ces deux tables.

1voto

RobS Points 6280

J'ai créé une application console VB et créé le schéma comme vous l'avez ici.

De plus, la relation est PK -> PK. Cela signifie-t-il que la relation est censée être individuelle ?

J'ai rempli les tableaux avec une ligne chacun (voir ci-dessous) et j'ai exécuté le code que vous avez énuméré ci-dessus. J'ai lancé SQL Profiler et il n'y a eu qu'une seule requête :

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]

Je voulais m'assurer que les Options de données forçaient un chargement profond, donc j'ai ajouté un peu de code supplémentaire - voici le code complet que j'ai utilisé (et seule la requête unique comme ci-dessus a été tracée) :

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

Voici les données du test :

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

0voto

andy Points 2411

Hé, je ne suis pas sûr d'avoir bien compris votre question, mais voici quelques informations,

Par défaut, LINQ to SQL adopte la liaison paresseuse, ce qui signifie qu'il n'interroge la base de données que lorsqu'il en a besoin. C'est pourquoi vous obtenez des requêtes multiples.

Il y a peu de choses que vous pouvez faire pour éviter les coups multiples sur la DB :

  1. Vous pouvez désactiver la liaison paresseuse globalement dans le concepteur LINQ to SQL. Mais alors vous devrez toujours effectuer des JOINS si vos tables ont des relations.

  2. Vous faites le JOIN manuellement dans la requête LINQ. Dans ce cas, vous devrez spécifier les "champs" que vous souhaitez renvoyer dans votre requête LINQ pour récupérer les données JOINÉES. Et si vous faites cela, alors vous retournerez un type anonyme

NOTE : LINQ to SQL ne supporte pas les LEFT JOINS. Si vous recherchez LINQ to SQL Left Joins sur Google, vous trouverez de nombreuses informations sur ce sujet particulier.

Santé, et bonne chance !

0voto

D. Lambert Points 1147

Va chercher LINQPad . C'est génial pour jouer avec des trucs comme ça.

Avez-vous essayé quelque chose comme ça ?

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}

0voto

Paul Lemke Points 2390

J'ai fini par utiliser le cadre de l'entité et tout va bien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X