MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

LINQ๋Š” ๊ฐ•๋ ฅํ•œ ์ƒˆ ๋ฐ์ดํ„ฐ ์กฐ์ž‘ ์–ธ์–ด๋กœ .NET์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. LINQ to SQL์„ ์‚ฌ์šฉํ•˜๋ฉด Entity Framework ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ DBMS์™€ ๋งค์šฐ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฅผ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๋Š” ์ฟผ๋ฆฌ ๊ฐ€๋Šฅํ•œ ๊ณต๊ธ‰์ž(์˜ˆ: Entity Framework)๊ฐ€ ์–ด๋–ค ์ข…๋ฅ˜์˜ SQL ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์‚ฌํ•ญ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด SQL Server์—์„œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค์Œ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ ์•ˆ์— ๋‘ ๊ฐœ์˜ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

ํ…Œ์ด๋ธ” ์ƒ์„ฑ

USE [TEST]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Ref](
	[ID] [int] NOT NULL,
	[ID2] [int] NOT NULL,
	[Name] [nvarchar](255) NOT NULL,
	[InsertUTCDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Ref] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Ref] ADD  CONSTRAINT [DF_Ref_InsertUTCDate]  DEFAULT (getutcdate()) FOR [InsertUTCDate]
GO

USE [TEST]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Customer](
	[ID] [int] NOT NULL,
	[Name] [nvarchar](255) NOT NULL,
	[Ref_ID] [int] NOT NULL,
	[InsertUTCDate] [datetime] NOT NULL,
	[Ref_ID2] [int] NOT NULL,
 CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Customer] ADD  CONSTRAINT [DF_Customer_Ref_ID]  DEFAULT ((0)) FOR [Ref_ID]
GO

ALTER TABLE [dbo].[Customer] ADD  CONSTRAINT [DF_Customer_InsertUTCDate]  DEFAULT (getutcdate()) FOR [InsertUTCDate]
GO

์ด์ œ ๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ Ref ํ…Œ์ด๋ธ”์„ ์ฑ„์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Ref ํ…Œ์ด๋ธ” ์ฑ„์šฐ๊ธฐ

USE [TEST]
GO

DECLARE @ind INT=1;

WHILE(@ind<1200000)
BEGIN
	INSERT INTO [dbo].[Ref]
           ([ID]
           ,[ID2]
           ,[Name])
    SELECT
           @ind
           ,@ind
           ,CAST(@ind AS NVARCHAR(255));

	SET @ind=@ind+1;
END 
GO

๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Customer ํ…Œ์ด๋ธ”์„ ์ฑ„์›Œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ณ ๊ฐ ํ…Œ์ด๋ธ” ์ฑ„์šฐ๊ธฐ

USE [TEST]
GO

DECLARE @ind INT=1;
DECLARE @ind_ref INT=1;

WHILE(@ind<=12000000)
BEGIN
	IF(@ind%3=0) SET @ind_ref=1;
	ELSE IF (@ind%5=0) SET @ind_ref=2;
	ELSE IF (@ind%7=0) SET @ind_ref=3;
	ELSE IF (@ind%11=0) SET @ind_ref=4;
	ELSE IF (@ind%13=0) SET @ind_ref=5;
	ELSE IF (@ind%17=0) SET @ind_ref=6;
	ELSE IF (@ind%19=0) SET @ind_ref=7;
	ELSE IF (@ind%23=0) SET @ind_ref=8;
	ELSE IF (@ind%29=0) SET @ind_ref=9;
	ELSE IF (@ind%31=0) SET @ind_ref=10;
	ELSE IF (@ind%37=0) SET @ind_ref=11;
	ELSE SET @ind_ref=@ind%1190000;
	
	INSERT INTO [dbo].[Customer]
	           ([ID]
	           ,[Name]
	           ,[Ref_ID]
	           ,[Ref_ID2])
	     SELECT
	           @ind,
	           CAST(@ind AS NVARCHAR(255)),
	           @ind_ref,
	           @ind_ref;


	SET @ind=@ind+1;
END
GO

๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” ๋‘ ๊ฐœ์˜ ํ…Œ์ด๋ธ”์„ ์–ป์—ˆ๋Š”๋ฐ, ๊ทธ ์ค‘ ํ•˜๋‚˜์—๋Š” 1๋งŒ ๊ฐœ๊ฐ€ ๋„˜๋Š” ๋ฐ์ดํ„ฐ ํ–‰์ด ์žˆ๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜์—๋Š” 10์ฒœ๋งŒ ๊ฐœ๊ฐ€ ๋„˜๋Š” ๋ฐ์ดํ„ฐ ํ–‰์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ Visual Studio์—์„œ ํ…Œ์ŠคํŠธ Visual C# ์ฝ˜์†” ์•ฑ(.NET Framework) ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

๋‹ค์Œ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  Entity Framework์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ํ”„๋กœ์ ํŠธ๋ฅผ ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ์œผ๋กœ ํด๋ฆญํ•˜๊ณ  ์ƒํ™ฉ์— ๋งž๋Š” ๋ฉ”๋‰ด์—์„œ NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚˜ํƒ€๋‚˜๋Š” NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ ์ฐฝ์˜ ๊ฒ€์ƒ‰ ์ฐฝ์— "Entity Framework"๋ผ๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๊ณ  Entity Framework ํŒจํ‚ค์ง€๋ฅผ ์„ ํƒํ•˜์—ฌ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

๋‹ค์Œ์œผ๋กœ App.config ํŒŒ์ผ์—์„œ configSections ์š”์†Œ๋ฅผ ๋‹ซ์€ ํ›„ ๋‹ค์Œ ๋ธ”๋ก์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<connectionStrings>
    <add name="DBConnection" connectionString="data source=ะ˜ะœะฏ_ะญะšะ—ะ•ะœะŸะ›ะฏะ ะ_MSSQL;Initial Catalog=TEST;Integrated Security=True;" providerName="System.Data.SqlClient" />
</connectionStrings>

ConnectionString์— ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ณ„๋„์˜ ํŒŒ์ผ์— 3๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. IBaseEntityID ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
    namespace TestLINQ
    {
        public interface IBaseEntityID
        {
            int ID { get; set; }
        }
    }
    

  2. IBaseEntityName ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
    namespace TestLINQ
    {
        public interface IBaseEntityName
        {
            string Name { get; set; }
        }
    }
    

  3. IBaseNameInsertUTCDate ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
    namespace TestLINQ
    {
        public interface IBaseNameInsertUTCDate
        {
            DateTime InsertUTCDate { get; set; }
        }
    }
    

๊ทธ๋ฆฌ๊ณ  ๋ณ„๋„์˜ ํŒŒ์ผ์—์„œ ๊ณตํ†ต ํ•„๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋‘ ์—”ํ„ฐํ‹ฐ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ํด๋ž˜์Šค BaseEntity๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ํด๋ž˜์Šค BaseEntity ๊ตฌํ˜„

namespace TestLINQ
{
    public class BaseEntity : IBaseEntityID, IBaseEntityName, IBaseNameInsertUTCDate
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public DateTime InsertUTCDate { get; set; }
    }
}

๋‹ค์Œ์œผ๋กœ ๋ณ„๋„์˜ ํŒŒ์ผ์— ๋‘ ์—”ํ„ฐํ‹ฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  1. Ref ํด๋ž˜์Šค ๊ตฌํ˜„
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestLINQ
    {
        [Table("Ref")]
        public class Ref : BaseEntity
        {
            public int ID2 { get; set; }
        }
    }
    

  2. Customer ํด๋ž˜์Šค ๊ตฌํ˜„
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestLINQ
    {
        [Table("Customer")]
        public class Customer: BaseEntity
        {
            public int Ref_ID { get; set; }
            public int Ref_ID2 { get; set; }
        }
    }
    

์ด์ œ ๋ณ„๋„์˜ ํŒŒ์ผ์— UserContext ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

UserContex ํด๋ž˜์Šค ๊ตฌํ˜„

using System.Data.Entity;

namespace TestLINQ
{
    public class UserContext : DbContext
    {
        public UserContext()
            : base("DbConnection")
        {
            Database.SetInitializer<UserContext>(null);
        }

        public DbSet<Customer> Customer { get; set; }
        public DbSet<Ref> Ref { get; set; }
    }
}

์šฐ๋ฆฌ๋Š” MS SQL Server์šฉ EF๋ฅผ ํ†ตํ•ด LINQ to SQL๋กœ ์ตœ์ ํ™” ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์„ฑ ์†”๋ฃจ์…˜์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

์ด์ œ Program.cs ํŒŒ์ผ์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

Program.cs ํŒŒ์ผ

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestLINQ
{
    class Program
    {
        static void Main(string[] args)
        {
            using (UserContext db = new UserContext())
            {
                var dblog = new List<string>();
                db.Database.Log = dblog.Add;

                var query = from e1 in db.Customer
                            from e2 in db.Ref
                            where (e1.Ref_ID == e2.ID)
                                 && (e1.Ref_ID2 == e2.ID2)
                            select new { Data1 = e1.Name, Data2 = e2.Name };

                var result = query.Take(1000).ToList();

                Console.WriteLine(dblog[1]);

                Console.ReadKey();
            }
        }
    }
}

๋‹ค์Œ์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž‘์—…์ด ๋๋‚˜๋ฉด ์ฝ˜์†”์— ๋‹ค์Œ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ƒ์„ฑ๋œ SQL ์ฟผ๋ฆฌ

SELECT TOP (1000) 
    [Extent1].[Ref_ID] AS [Ref_ID], 
    [Extent1].[Name] AS [Name], 
    [Extent2].[Name] AS [Name1]
    FROM  [dbo].[Customer] AS [Extent1]
    INNER JOIN [dbo].[Ref] AS [Extent2] ON ([Extent1].[Ref_ID] = [Extent2].[ID]) AND ([Extent1].[Ref_ID2] = [Extent2].[ID2])

์ฆ‰, ์ผ๋ฐ˜์ ์œผ๋กœ LINQ ์ฟผ๋ฆฌ๋Š” MS SQL Server DBMS์— ๋Œ€ํ•œ SQL ์ฟผ๋ฆฌ๋ฅผ ๋งค์šฐ ์ž˜ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ LINQ ์ฟผ๋ฆฌ์—์„œ AND ์กฐ๊ฑด์„ OR๋กœ ๋ณ€๊ฒฝํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

LINQ ์ฟผ๋ฆฌ

var query = from e1 in db.Customer
                            from e2 in db.Ref
                            where (e1.Ref_ID == e2.ID)
                                || (e1.Ref_ID2 == e2.ID2)
                            select new { Data1 = e1.Name, Data2 = e2.Name };

๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

30์ดˆ๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๋ช…๋ น ์‹คํ–‰ ์‹œ๊ฐ„์œผ๋กœ ์ธํ•ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด์„œ ์‹คํ–‰์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

LINQ์—์„œ ์ƒ์„ฑ๋œ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด
, ๊ทธ๋Ÿฌ๋ฉด ๋‘ ์„ธํŠธ(ํ…Œ์ด๋ธ”)์˜ ๋ฐ์นด๋ฅดํŠธ ๊ณฑ์„ ํ†ตํ•ด ์„ ํƒ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒ์„ฑ๋œ SQL ์ฟผ๋ฆฌ

SELECT TOP (1000) 
    [Extent1].[Ref_ID] AS [Ref_ID], 
    [Extent1].[Name] AS [Name], 
    [Extent2].[Name] AS [Name1]
    FROM  [dbo].[Customer] AS [Extent1]
    CROSS JOIN [dbo].[Ref] AS [Extent2]
    WHERE [Extent1].[Ref_ID] = [Extent2].[ID] OR [Extent1].[Ref_ID2] = [Extent2].[ID2]

LINQ ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค์‹œ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ตœ์ ํ™”๋œ LINQ ์ฟผ๋ฆฌ

var query = (from e1 in db.Customer
                   join e2 in db.Ref
                   on e1.Ref_ID equals e2.ID
                   select new { Data1 = e1.Name, Data2 = e2.Name }).Union(
                        from e1 in db.Customer
                        join e2 in db.Ref
                        on e1.Ref_ID2 equals e2.ID2
                        select new { Data1 = e1.Name, Data2 = e2.Name });

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ SQL ์ฟผ๋ฆฌ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

SQL ์ฟผ๋ฆฌ

SELECT 
    [Limit1].[C1] AS [C1], 
    [Limit1].[C2] AS [C2], 
    [Limit1].[C3] AS [C3]
    FROM ( SELECT DISTINCT TOP (1000) 
        [UnionAll1].[C1] AS [C1], 
        [UnionAll1].[Name] AS [C2], 
        [UnionAll1].[Name1] AS [C3]
        FROM  (SELECT 
            1 AS [C1], 
            [Extent1].[Name] AS [Name], 
            [Extent2].[Name] AS [Name1]
            FROM  [dbo].[Customer] AS [Extent1]
            INNER JOIN [dbo].[Ref] AS [Extent2] ON [Extent1].[Ref_ID] = [Extent2].[ID]
        UNION ALL
            SELECT 
            1 AS [C1], 
            [Extent3].[Name] AS [Name], 
            [Extent4].[Name] AS [Name1]
            FROM  [dbo].[Customer] AS [Extent3]
            INNER JOIN [dbo].[Ref] AS [Extent4] ON [Extent3].[Ref_ID2] = [Extent4].[ID2]) AS [UnionAll1]
    )  AS [Limit1]

์•„์‰ฝ๊ฒŒ๋„ LINQ ์ฟผ๋ฆฌ์—๋Š” ํ•˜๋‚˜์˜ ์กฐ์ธ ์กฐ๊ฑด๋งŒ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ์—์„œ๋Š” ๊ฐ ์กฐ๊ฑด์— ๋Œ€ํ•ด ๋‘ ๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™๋“ฑํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“  ๋‹ค์Œ Union์„ ํ†ตํ•ด ๊ฒฐํ•ฉํ•˜์—ฌ ํ–‰ ๊ฐ„์˜ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ, ์™„์ „ํ•œ ์ค‘๋ณต ํ–‰์ด ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ณ ๋ คํ•˜๋ฉด ์ฟผ๋ฆฌ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋™์ผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ ์ƒํ™œ์—์„œ๋Š” ์™„์ „ํ•œ ์ค‘๋ณต ๋ผ์ธ์ด ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์‚ฌ๋žŒ๋“ค์€ ์ด๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์ด ๋‘ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ๊ณ„ํš์„ ๋น„๊ตํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. CROSS JOIN์˜ ๊ฒฝ์šฐ ํ‰๊ท  ์‹คํ–‰ ์‹œ๊ฐ„์€ 195์ดˆ์ž…๋‹ˆ๋‹ค.
    MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด
  2. INNER JOIN-UNION์˜ ๊ฒฝ์šฐ ํ‰๊ท  ์‹คํ–‰ ์‹œ๊ฐ„์€ 24์ดˆ ๋ฏธ๋งŒ์ž…๋‹ˆ๋‹ค.
    MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด

๊ฒฐ๊ณผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ์ˆ˜๋ฐฑ๋งŒ ๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ๋‘ ํ…Œ์ด๋ธ”์˜ ๊ฒฝ์šฐ ์ตœ์ ํ™”๋œ LINQ ์ฟผ๋ฆฌ๊ฐ€ ์ตœ์ ํ™”๋˜์ง€ ์•Š์€ ์ฟผ๋ฆฌ๋ณด๋‹ค ๋ช‡ ๋ฐฐ ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค.

์กฐ๊ฑด์— AND๊ฐ€ ํฌํ•จ๋œ ์˜ต์…˜์˜ ๊ฒฝ์šฐ ๋‹ค์Œ ํ˜•์‹์˜ LINQ ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

LINQ ์ฟผ๋ฆฌ

var query = from e1 in db.Customer
                            from e2 in db.Ref
                            where (e1.Ref_ID == e2.ID)
                                 && (e1.Ref_ID2 == e2.ID2)
                            select new { Data1 = e1.Name, Data2 = e2.Name };

๊ฑฐ์˜ ํ•ญ์ƒ ์˜ฌ๋ฐ”๋ฅธ SQL ์ฟผ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ ํ‰๊ท ์ ์œผ๋กœ ์•ฝ 1์ดˆ ๋‚ด์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

MS SQL Server์šฉ C#.NET์—์„œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด
๋˜ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฟผ๋ฆฌ ๋Œ€์‹  LINQ to Objects ์กฐ์ž‘์˜ ๊ฒฝ์šฐ:

LINQ ์ฟผ๋ฆฌ(์ฒซ ๋ฒˆ์งธ ์˜ต์…˜)

var query = from e1 in seq1
                            from e2 in seq2
                            where (e1.Key1==e2.Key1)
                               && (e1.Key2==e2.Key2)
                            select new { Data1 = e1.Data, Data2 = e2.Data };

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

LINQ ์ฟผ๋ฆฌ(์ฒซ ๋ฒˆ์งธ ์˜ต์…˜)

var query = from e1 in seq1
                            join e2 in seq2
                            on new { e1.Key1, e1.Key2 } equals new { e2.Key1, e2.Key2 }
                            select new { Data1 = e1.Data, Data2 = e2.Data };

์ง€์—ญ :

๋‘ ๊ฐœ์˜ ๋ฐฐ์—ด ์ •์˜

Para[] seq1 = new[] { new Para { Key1 = 1, Key2 = 2, Data = "777" }, new Para { Key1 = 2, Key2 = 3, Data = "888" }, new Para { Key1 = 3, Key2 = 4, Data = "999" } };
Para[] seq2 = new[] { new Para { Key1 = 1, Key2 = 2, Data = "777" }, new Para { Key1 = 2, Key2 = 3, Data = "888" }, new Para { Key1 = 3, Key2 = 5, Data = "999" } };

, Para ์œ ํ˜•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋ฉ๋‹ˆ๋‹ค.

ํŒŒ๋ผ ์œ ํ˜• ์ •์˜

class Para
{
        public int Key1, Key2;
        public string Data;
}

๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” MS SQL Server์— ๋Œ€ํ•œ LINQ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ ์žˆ์–ด ๋ช‡ ๊ฐ€์ง€ ์ธก๋ฉด์„ ์กฐ์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ถˆํ–‰ํ•˜๊ฒŒ๋„ ๊ฒฝํ—˜์ด ๋งŽ๊ณ  ์„ ๋„์ ์ธ .NET ๊ฐœ๋ฐœ์ž๋ผ๋„ ์ž์‹ ์ด ์‚ฌ์šฉํ•˜๋Š” ์ง€์นจ์ด ์ด๋ฉด์—์„œ ์ˆ˜ํ–‰๋˜๋Š” ์ž‘์—…์„ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ์žŠ์–ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ทธ๋“ค์€ ๊ตฌ์„ฑ์ž๊ฐ€ ๋˜์–ด ์†Œํ”„ํŠธ์›จ์–ด ์†”๋ฃจ์…˜์„ ํ™•์žฅํ•  ๋•Œ๋‚˜ ์™ธ๋ถ€ ํ™˜๊ฒฝ ์กฐ๊ฑด์ด ์•ฝ๊ฐ„ ๋ณ€๊ฒฝ๋  ๋•Œ ๋ฏธ๋ž˜์— ์‹œํ•œํญํƒ„์„ ์‹ฌ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ๋ฆฌ๋ทฐ๋„ ์ง„ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค ์—ฌ๊ธฐ์—.

ํ…Œ์ŠคํŠธ ์†Œ์Šค - ํ”„๋กœ์ ํŠธ ์ž์ฒด, TEST ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ํ…Œ์ด๋ธ” ์ƒ์„ฑ, ์ด๋Ÿฌํ•œ ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ ์ฑ„์šฐ๊ธฐ ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—.
๋˜ํ•œ ์ด ์ €์žฅ์†Œ์˜ Plans ํด๋”์—๋Š” OR ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ณ„ํš์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€