MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“

LINQ เชเช• เชถเช•เซเชคเชฟเชถเชพเชณเซ€ เชจเชตเซ€ เชกเซ‡เชŸเชพ เชฎเซ‡เชจเซ€เชชเซเชฏเซเชฒเซ‡เชถเชจ เชฒเซ‡เช‚เช—เซเชตเซ‡เชœ เชคเชฐเซ€เช•เซ‡ .NET เชฆเชพเช–เชฒ เช•เชฐเซเชฏเซเช‚. เชคเซ‡เชจเชพ เชญเชพเช— เชฐเซ‚เชชเซ‡ LINQ เชฅเซ€ SQL เชคเชฎเชจเซ‡ DBMS เชธเชพเชฅเซ‡, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชเชจเซเชŸเชฟเชŸเซ€ เชซเซเชฐเซ‡เชฎเชตเชฐเซเช•เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช–เซ‚เชฌ เช…เชจเซเช•เซ‚เชณ เชฐเซ€เชคเซ‡ เชตเชพเชคเชšเซ€เชค เช•เชฐเชตเชพเชจเซ€ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเซ‡ เช›เซ‡. เชœเซ‹ เช•เซ‡, เช˜เชฃเซ€ เชตเชพเชฐ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡, เชตเชฟเช•เชพเชธเช•เชฐเซเชคเชพเช“ เช เชœเซ‹เชตเชพเชจเซเช‚ เชญเซ‚เชฒเซ€ เชœเชพเชฏ เช›เซ‡ เช•เซ‡ เชคเชฎเชพเชฐเชพ เช•เชฟเชธเซเชธเชพเชฎเชพเช‚ เชเชจเซเชŸเชฟเชŸเซ€ เชซเซเชฐเซ‡เชฎเชตเชฐเซเช•, เช•เซเชตเซ‡เชฐเซ€ เช•เชฐเชตเชพ เชฏเซ‹เช—เซเชฏ เชชเซเชฐเชฆเชพเชคเชพ เช•เซ‡เชตเชพ เชชเซเชฐเช•เชพเชฐเชจเซ€ SQL เช•เซเชตเซ‡เชฐเซ€ เชœเชจเชฐเซ‡เชŸ เช•เชฐเชถเซ‡.

เชšเชพเชฒเซ‹ เช‰เชฆเชพเชนเชฐเชฃเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชฌเซ‡ เชฎเซเช–เซเชฏ เชฎเซเชฆเซเชฆเชพเช“ เชœเซ‹เชˆเช.
เช† เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, SQL เชธเชฐเซเชตเชฐเชฎเชพเช‚ เชŸเซ‡เชธเซเชŸ เชกเซ‡เชŸเชพเชฌเซ‡เช เชฌเชจเชพเชตเซ‹ เช…เชจเซ‡ เชจเซ€เชšเซ‡เชจเซ€ เช•เซเชตเซ‡เชฐเซ€เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชคเซ‡เชฎเชพเช‚ เชฌเซ‡ เช•เซ‹เชทเซเชŸเช•เซ‹ เชฌเชจเชพเชตเซ‹:

เช•เซ‹เชทเซเชŸเช•เซ‹ เชฌเชจเชพเชตเซ€ เชฐเชนเซเชฏเชพ เช›เซ€เช

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

เชนเชตเซ‡ เชšเชพเชฒเซ‹ เชจเซ€เชšเซ‡เชจเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชšเชฒเชพเชตเซ€เชจเซ‡ เชฐเซ‡เชซ เชŸเซ‡เชฌเชฒ เชคเซˆเชฏเชพเชฐ เช•เชฐเซ€เช:

เชฐเซ‡เชซ เชŸเซ‡เชฌเชฒ เชญเชฐเชตเซเช‚

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

เชšเชพเชฒเซ‹ เช เชœ เชฐเซ€เชคเซ‡ เชจเซ€เชšเซ‡เชจเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช—เซเชฐเชพเชนเช• เช•เซ‹เชทเซเชŸเช• เชญเชฐเซ€เช:

เช—เซเชฐเชพเชนเช• เช•เซ‹เชทเซเชŸเช•เชจเซ€ เชตเชธเซเชคเซ€

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 เชฎเชฟเชฒเชฟเชฏเชจเชฅเซ€ เชตเชงเซ เชชเช‚เช•เซเชคเชฟเช“ เชกเซ‡เชŸเชพ เช›เซ‡.

เชนเชตเซ‡ เชตเชฟเชเซเชฏเซเช…เชฒ เชธเซเชŸเซเชกเชฟเชฏเซ‹เชฎเชพเช‚ เชคเชฎเชพเชฐเซ‡ เชŸเซ‡เชธเซเชŸ เชตเชฟเชเซเชฏเซเช…เชฒ C# เช•เชจเซเชธเซ‹เชฒ เชเชช (.NET เชซเซเชฐเซ‡เชฎเชตเชฐเซเช•) เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸ เชฌเชจเชพเชตเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡:

MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“

เช†เช—เชณ, เชคเชฎเชพเชฐเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เช เชธเชพเชฅเซ‡ เช•เซเชฐเชฟเชฏเชพเชชเซเชฐเชคเชฟเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชเชจเซเชŸเชฟเชŸเซ€ เชซเซเชฐเซ‡เชฎเชตเชฐเซเช• เชฎเชพเชŸเซ‡ เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€ เช‰เชฎเซ‡เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡.
เชคเซ‡เชจเซ‡ เช‰เชฎเซ‡เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸ เชชเชฐ เชœเชฎเชฃเซเช‚-เช•เซเชฒเชฟเช• เช•เชฐเซ‹ เช…เชจเซ‡ เชธเช‚เชฆเชฐเซเชญ เชฎเซ‡เชจเซ‚เชฎเชพเช‚เชฅเซ€ NuGet Packages เชฎเซ‡เชจเซ‡เชœ เช•เชฐเซ‹ เชชเชธเช‚เชฆ เช•เชฐเซ‹:

MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“

เชชเช›เซ€, เชฆเซ‡เช–เชพเชคเซ€ NuGet เชชเซ‡เช•เซ‡เชœ เชฎเซ‡เชจเซ‡เชœเชฎเซ‡เชจเซเชŸ เชตเชฟเชจเซเชกเซ‹เชฎเชพเช‚, เชธเชฐเซเชš เชตเชฟเชจเซเชกเซ‹เชฎเชพเช‚ "เชเชจเซเชŸเชฟเชŸเซ€ เชซเซเชฐเซ‡เชฎเชตเชฐเซเช•" เชถเชฌเซเชฆ เชฆเชพเช–เชฒ เช•เชฐเซ‹ เช…เชจเซ‡ เชเชจเซเชŸเชฟเชŸเซ€ เชซเซเชฐเซ‡เชฎเชตเชฐเซเช• เชชเซ‡เช•เซ‡เชœ เชชเชธเช‚เชฆ เช•เชฐเซ‹ เช…เชจเซ‡ เชคเซ‡เชจเซ‡ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเซ‹:

MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ 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>

เช•เชจเซ‡เช•เซเชถเชจเชธเซเชŸเซเชฐเชฟเช‚เช—เชฎเชพเช‚ เชคเชฎเชพเชฐเซ‡ เช•เชจเซ‡เช•เซเชถเชจ เชธเซเชŸเซเชฐเชฟเช‚เช— เชฆเชพเช–เชฒ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡.

เชนเชตเซ‡ เชšเชพเชฒเซ‹ เช…เชฒเช— เชซเชพเชˆเชฒเซ‹เชฎเชพเช‚ 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. เชธเช‚เชฆเชฐเซเชญ เชตเชฐเซเช—เชจเซเช‚ เช…เชฎเชฒเซ€เช•เชฐเชฃ
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestLINQ
    {
        [Table("Ref")]
        public class Ref : BaseEntity
        {
            public int ID2 { get; set; }
        }
    }
    

  2. เช—เซเชฐเชพเชนเช• เชตเชฐเซเช—เชจเซเช‚ เช…เชฎเชฒเซ€เช•เชฐเชฃ
    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 เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ EF เชฆเซเชตเชพเชฐเชพ LINQ เชฅเซ€ SQL เชธเชพเชฅเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เชเซ‡เชถเชจ เชชเชฐเซ€เช•เซเชทเชฃเซ‹ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชคเซˆเชฏเชพเชฐ เช‰เช•เซ‡เชฒ เชชเซเชฐเชพเชชเซเชค เชฅเชฏเซ‹ เช›เซ‡:

MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ 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 เชธเชฐเซเชตเชฐ 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 เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“

เชœเซ‹ เชคเชฎเซ‡ LINQ เชฆเซเชตเชพเชฐเชพ เชœเชจเชฐเซ‡เชŸ เช•เชฐเชพเชฏเซ‡เชฒเซ€ เช•เซเชตเซ‡เชฐเซ€ เชœเซเช“:

MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ 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 เช•เซเชตเซ‡เชฐเซ€เชเชฎเชพเช‚ เชซเช•เซเชค เชเช• เชœ เชœเซ‹เชกเชตเชพเชจเซ€ เชถเชฐเชค เชนเซ‹เชˆ เชถเช•เซ‡ เช›เซ‡, เชคเซ‡เชฅเซ€ เช…เชนเซ€เช‚ เชฆเชฐเซ‡เช• เชถเชฐเชค เชฎเชพเชŸเซ‡ เชฌเซ‡ เช•เซเชตเซ‡เชฐเซ€เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช…เชจเซ‡ เชชเช›เซ€ เชชเช‚เช•เซเชคเชฟเช“เชฎเชพเช‚เชฅเซ€ เชกเซเชชเซเชฒเชฟเช•เซ‡เชŸเซเชธ เชฆเซ‚เชฐ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชฏเซเชจเชฟเชฏเชจ เชฆเซเชตเชพเชฐเชพ เชคเซ‡เชฎเชจเซ‡ เชœเซ‹เชกเซ€เชจเซ‡ เชธเชฎเช•เช•เซเชท เช•เซเชตเซ‡เชฐเซ€ เช•เชฐเชตเซ€ เชถเช•เซเชฏ เช›เซ‡.
เชนเชพ, เช•เซเชตเซ‡เชฐเซ€ เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ เชฌเชฟเชจ-เชธเชฎเชพเชจ เชนเชถเซ‡, เชคเซ‡ เชงเซเชฏเชพเชจเชฎเชพเช‚ เชฒเซ‡เชคเชพ เช•เซ‡ เชธเช‚เชชเซ‚เชฐเซเชฃ เชกเซเชชเซเชฒเชฟเช•เซ‡เชŸ เชชเช‚เช•เซเชคเชฟเช“ เชชเชฐเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เชถเช•เซ‡ เช›เซ‡. เชœเซ‹ เช•เซ‡, เชตเชพเชธเซเชคเชตเชฟเช• เชœเซ€เชตเชจเชฎเชพเช‚, เชธเช‚เชชเซ‚เชฐเซเชฃ เชกเซเชชเซเชฒเชฟเช•เซ‡เชŸ เชฒเชพเช‡เชจเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€ เช…เชจเซ‡ เชฒเซ‹เช•เซ‹ เชคเซ‡เชฎเชพเช‚เชฅเซ€ เช›เซ‚เชŸเช•เชพเชฐเซ‹ เชฎเซ‡เชณเชตเชตเชพเชจเซ‹ เชชเซเชฐเชฏเชพเชธ เช•เชฐเซ‡ เช›เซ‡.

เชนเชตเซ‡ เชšเชพเชฒเซ‹ เช† เชฌเซ‡ เชชเซเชฐเชถเซเชจเซ‹เชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃ เชฏเซ‹เชœเชจเชพเช“เชจเซ€ เชคเซเชฒเชจเชพ เช•เชฐเซ€เช:

  1. CROSS JOIN เชฎเชพเชŸเซ‡ เชธเชฐเซ‡เชฐเชพเชถ เช…เชฎเชฒ เชธเชฎเชฏ 195 เชธเซ‡เช•เชจเซเชก เช›เซ‡:
    MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“
  2. INNER JoIN-UNION เชฎเชพเชŸเซ‡ เชธเชฐเซ‡เชฐเชพเชถ เช…เชฎเชฒ เชธเชฎเชฏ 24 เชธเซ‡เช•เชจเซเชก เช•เชฐเชคเชพเช‚ เช“เช›เซ‹ เช›เซ‡:
    MS SQL เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“

ะšะฐะบ ะฒะธะดะฝะพ ะธะท ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะฒ, ะดะปั ะดะฒัƒั… ั‚ะฐะฑะปะธั† ั ะผะธะปะปะธะพะฝะฐะผะธ ะทะฐะฟะธัะตะน ะพะฟั‚ะธะผะธะทะธั€ะพะฒะฐะฝะฝั‹ะน LINQ-ะทะฐะฟั€ะพั ั€ะฐะฑะพั‚ะฐะตั‚ ะฒ ั€ะฐะทั‹ ะฑั‹ัั‚ั€ะตะต, ั‡ะตะผ ะฝะตะพะฟั‚ะธะผะธะทะธั€ะพะฒะฐะฝะฝั‹ะน.

ะ”ะปั ะฒะฐั€ะธะฐะฝั‚ะฐ ั ะ˜ ะฒ ัƒัะปะพะฒะธัั… 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 เชธเชฐเซเชตเชฐ เชฎเชพเชŸเซ‡ C#.NET เชฎเชพเช‚ LINQ เช•เซเชตเซ‡เชฐเซ€เชเชจเซ‡ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเชพเชจเชพ เช•เซ‡เชŸเชฒเชพเช• เชชเชพเชธเชพเช“
ะขะฐะบะถะต ะดะปั ะผะฐะฝะธะฟัƒะปัั†ะธะน LINQ to Objects ะฒะผะตัั‚ะพ ะทะฐะฟั€ะพัะฐ ะฒะธะดะฐ:

LINQ-ะทะฐะฟั€ะพั (1-ะน ะฒะฐั€ะธะฐะฝั‚)

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-ะทะฐะฟั€ะพั (2-ะน ะฒะฐั€ะธะฐะฝั‚)

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 ะพะฟั€ะตะดะตะปัะตั‚ัั ัะปะตะดัƒัŽั‰ะธะผ ะพะฑั€ะฐะทะพะผ:

ะžะฟั€ะตะดะตะปะตะฝะธะต ั‚ะธะฟะฐ Para

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

ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ ะผั‹ ั€ะฐััะผะพั‚ั€ะตะปะธ ะฝะตะบะพั‚ะพั€ั‹ะต ะฐัะฟะตะบั‚ั‹ ะฒ ะพะฟั‚ะธะผะธะทะฐั†ะธะธ LINQ-ะทะฐะฟั€ะพัะพะฒ ะบ MS SQL Server.

ะš ัะพะถะฐะปะตะฝะธัŽ ะดะฐะถะต ะพะฟั‹ั‚ะฝั‹ะต ะธ ะฒะตะดัƒั‰ะธะต .NET-ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะธ ะทะฐะฑั‹ะฒะฐัŽั‚ ะพ ั‚ะพะผ, ั‡ั‚ะพ ะฝะตะพะฑั…ะพะดะธะผะพ ะฟะพะฝะธะผะฐั‚ัŒ ั‡ั‚ะพ ะดะตะปะฐัŽั‚ ะทะฐ ะบะฐะดั€ะพะผ ั‚ะต ะธะฝัั‚ั€ัƒะบั†ะธะธ, ะบะพั‚ะพั€ั‹ะต ะพะฝะธ ะธัะฟะพะปัŒะทัƒัŽั‚. ะ˜ะฝะฐั‡ะต ะพะฝะธ ัั‚ะฐะฝะพะฒัั‚ัั ะบะพะฝั„ะธะณัƒั€ะฐั‚ะพั€ะฐะผะธ ะธ ะผะพะณัƒั‚ ะทะฐะปะพะถะธั‚ัŒ ะฑะพะผะฑัƒ ะทะฐะผะตะดะปะตะฝะฝะพะณะพ ะดะตะนัั‚ะฒะธั ะฒ ะฑัƒะดัƒั‰ะตะผ ะบะฐะบ ะฟั€ะธ ะผะฐััˆั‚ะฐะฑะธั€ะพะฒะฐะฝะธะธ ะฟั€ะพะณั€ะฐะผะผะฝะพะณะพ ั€ะตัˆะตะฝะธั, ั‚ะฐะบ ะธ ะฟั€ะธ ะฝะตะทะฝะฐั‡ะธั‚ะตะปัŒะฝั‹ั… ะธะทะผะตะฝะตะฝะธัั… ะฒะฝะตัˆะฝะธั… ัƒัะปะพะฒะธะน ัั€ะตะดั‹.

ะขะฐะบะถะต ะฝะตะฑะพะปัŒัˆะพะน ะพะฑะทะพั€ ะฟั€ะพะฒะพะดะธะปัั ะธ เช…เชนเซ€เช‚.

ะ˜ัั…ะพะดะฝะธะบะธ ะดะปั ั‚ะตัั‚ะฐ-ัะฐะผ ะฟั€ะพะตะบั‚, ัะพะทะดะฐะฝะธะต ั‚ะฐะฑะปะธั† ะฒ ะฑะฐะทะต ะดะฐะฝะฝั‹ั… TEST, ะฐ ั‚ะฐะบะถะต ะฝะฐะฟะพะปะฝะตะฝะธะต ะดะฐะฝะฝั‹ะผะธ ัั‚ะธั… ั‚ะฐะฑะปะธั† ะฝะฐั…ะพะดะธั‚ัั เช…เชนเซ€เช‚.
เช† เชฐเซ€เชชเซ‹เชเซ€เชŸเชฐเซ€เชฎเชพเช‚, เชชเซเชฒเชพเชจ เชซเซ‹เชฒเซเชกเชฐเชฎเชพเช‚, OR เชถเชฐเชคเซ‹ เชธเชพเชฅเซ‡ เช•เซเชตเซ‡เชฐเซ€ เชšเชฒเชพเชตเชตเชพ เชฎเชพเชŸเซ‡เชจเซ€ เชฏเซ‹เชœเชจเชพเช“ เช›เซ‡.

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹