LINQ to SQL: внутреннее соединение с ручной связью в SQL 2000 - PullRequest
2 голосов
/ 05 февраля 2009

У меня есть две таблицы в отношениях один ко многим. (цены на продукты и кол-во). На уровне базы данных я не могу создать связь между двумя таблицами. Я перенес эти две таблицы в LINQ и создал связь вручную.

Мне нужно выполнить большой запрос LINQ и объединить таблицы. Моя проблема в том, что он не использует соединение для получения данных. LINQ использует 1 выбор в основной таблице, затем 1 выбор для каждой строки в этой основной таблице.

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

Есть мысли о том, почему это может быть? Спасибо! Пол

РЕДАКТИРОВАТЬ: вот две таблицы:

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]

И другая таблица:

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]

DBML прост с двумя таблицами. Я создал связь между этими двумя таблицами: «commerce_product» - родитель, а «commerce_qty_break» - дочерний, к которому присоединился «PF_ID».

Я могу написать что-то вроде этого:

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

И я вижу, что он включается в таблицу в запросе, но как только я пытаюсь прокрутить "qty_breaks", он начинает выполнять select, чтобы получить эту информацию.

Я полностью в тупике.

Редактировать 2: Вот 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>

РЕДАКТИРОВАТЬ 3: Очевидно, это только проблема в SQL 2000. SQL 2008 работает нормально. У меня есть другие таблицы, которые активно загружаются в SQL 2000, и я не могу понять, в чем разница между этими двумя таблицами.

Ответы [ 4 ]

1 голос
/ 07 февраля 2009

Я создал консольное приложение VB и создал схему, как у вас здесь.

Кроме того, отношения - PK -> PK, значит ли это, что это отношения один к одному?

Я заполнил таблицы каждой строкой (см. Ниже) и запустил код, который вы перечислили выше. Я запустил SQL Profiler, и он только один раз запросил:

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]

Я хотел убедиться, что параметры данных вызывали глубокую загрузку, поэтому я добавил дополнительный код - вот полный код, который я использовал (и отслеживался только один запрос, как указано выше):

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

Вот данные теста:

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
0 голосов
/ 25 августа 2009

Я закончил тем, что использовал структуру лица, и все хорошо.

0 голосов
/ 11 февраля 2009

Захватите LINQPad . Отлично подходит для игры с такими вещами.

Вы пробовали что-то подобное?

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}
0 голосов
/ 05 февраля 2009

эй, не уверен, что я полностью понял ваш вопрос, но вот некоторая информация,

По умолчанию LINQ to SQL принимает ленивое связывание, что означает, что он не будет запрашивать базу данных, пока не потребуется. Вот почему вы получаете несколько запросов.

Есть несколько вещей, которые вы можете сделать, чтобы избежать нескольких попаданий в БД:

  1. Вы можете отключить ленивое связывание глобально в конструкторе LINQ to SQL. Но тогда вы всегда будете выполнять JOINS, если ваши таблицы имеют какие-либо отношения.

  2. Вы выполняете JOIN вручную в запросе LINQ. Если вы сделаете это, вам нужно будет указать, какие «поля» вы хотите вернуть в своем запросе LINQ, чтобы получить данные JOINED. И если вы сделаете это, вы будете возвращать анонимный тип

ПРИМЕЧАНИЕ: LINQ to SQL не поддерживает LEFT JOINS. Если вы перейдете в Google LINQ to SQL Left Joins, вы увидите много информации на эту тему

ура и удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...