Dbtype
Linq 2 Sqlã®ãšã³ãã£ãã£ããããã£ã«ã¯ã DbTypeãã³ãã®æå®ïŒåæåãé€ãã詳现ã¯ä»¥äžãåç §ïŒã¯å¿ èŠãããŸããã ãããŠç¢ºãã«ãééã£ãDbTypeãæå®ãã¹ãã§ã¯ãããŸããã ããšãã°ãããŒã¹ã®åã®ã¿ã€ããnvarcharïŒ50ïŒã§ããå Žåããã®åã®ã¿ã€ããncharïŒ50ïŒã§ããããšãLinq 2 Sqlã«ç€ºãå¿ èŠã¯ãããŸããã 次ã®äŸã®ããã«ããã®ãã£ãŒã«ããåŒå¥åã§ããå Žåãç¹ã«ãããè¡ã䟡å€ã¯ãããŸãã
[Table(Name = "directcrm.OperationSteps")] [InheritanceMapping(Code = "", Type = typeof(OperationStep), IsDefault = true)] // ... [InheritanceMapping(Code = "ApplySegment", Type = typeof(ApplySegmentOperationStep))] public class OperationStep : INotifyPropertyChanging, INotifyPropertyChanged, IValidatable { // ... [Column(Storage = "type", DbType = "nchar(50) NOT NULL", CanBeNull = false, IsDiscriminator = true)] public string Type { get { return type; } set { if ((type != value)) { SendPropertyChanging(); type = value; SendPropertyChanged(); } } } }
ããã§ã¯ãããŒã¿ããŒã¹ããOperationStepåã®ãšã³ãã£ãã£ãèªã¿åã£ãŠãç¶æ¿ãããã³ã°ã§åŠçã§ãããã©ããã確èªããŠã¿ãŸãããã
æåŸ ããªã
Typeããããã£ã«ã¯äžèŠæ£ããå€ãå«ãŸããŠããŸããããšã³ãã£ãã£ã®ã¿ã€ãã¯æ£ããå®çŸ©ãããŠããŸããã ã¿ã€ããæ£ããäžèŽãããããã«ãç¶æ¿ãããã³ã°ããã£ãŒã«ãã«è¡šç€ºãããã®ã¯äœã§ããïŒ OfTypeãè©ŠããŠã¿ãŸãããã
modelContext.Repositories.Get<OperationStepRepository>().Items.OfType<ApplySegmentOperationStep>().FirstOrDefault();
ãããŠãlinqãããã€ããŒã«ãã£ãŠçæãããSQLïŒ
DECLARE @p0 NChar = 'ApplySegment '; SELECT TOP (1) [t0].[Type], [t0].[SegmentationSystemName], [t0].[SegmentSystemName], [t0].[Id], [t0].[Order], [t0].[OperationStepGroupId], [t0].[OperationStepTypeSystemName], [t0].[IsMarker] FROM [directcrm].[OperationSteps] AS [t0] WHERE [t0].[Type] = @p0;
ååãšããŠããã©ã¡ãŒã¿ã®å€ã¯æ³å®ãããŠããŸãããããã®ãããªãã°ãæ€åºããããšã¯ããã»ã©ç°¡åã§ã¯ãããŸããã§ããã 泚æããŠãã ããã ãã°ã¯çŸåšåºçŸããŠããããšã¯æããã§ãããäžè¬çã«èšãã°ããšã³ãã£ãã£ãæ£ããäœæãããŠããŒã¿ããŒã¹ããåé€ããããããã·ã¹ãã ã«é·æéæ®ãå¯èœæ§ããããŸãã åŒå¥åšã®å€ã®å¥åŠãªå°Ÿã«æ³šæãæãããåŒå¥åšãæŽæ°ããã¹ã¯ãªããã®åŸã«ãã¹ãŠãèœã¡å§ãããŸã§ã
linq to sqlãšã³ãã£ãã£ã«enumãä¿åããããšã«ã€ããŠå°ã説æããŸãã
ããã©ã«ãã§Linq to sqlïŒ DbTypeãæå®ãããŠããªãå ŽåïŒã¯ãEnumã®åã¿ã€ããIntã§ãããšèŠãªããŸãã ãããã£ãŠã次ã®ãšã³ãã£ãã£ãæäœããããšã¯ã§ããŸããïŒ directcrm.CustomersããŒãã«ã®Sexãã£ãŒã«ãã¯nvarcharïŒ15ïŒã¿ã€ãã§ãïŒïŒ
[Table(Name = "directcrm.Customers")] public sealed class Customer : INotifyPropertyChanging, INotifyPropertyChanged, IValidatable { // [Column(Storage = "sex", CanBeNull = true)] public Sex? Sex { get { return sex; } set { if (sex != value) { SendPropertyChanging(); sex = value; SendPropertyChanged(); } } } }
ããŒã¹ããæžç®ããããšãããšãCustomerãšã³ãã£ãã£ïŒSexãã£ãŒã«ãã«ã¯æååãfemaleããå ¥åãããŸãïŒã¯ã System.InvalidCastExceptionããèœã¡ãŸãã æå®ãããæ§å¥ã§æ¶è²»è ãä¿åãããšãããã®ãªã¯ãšã¹ããååŸããŸãïŒ
DECLARE @p20 Int = 1 INSERT INTO [directcrm].[Customers](..., [Sex], ...) VALUES (..., @p7, ...)
泚ç®ã«å€ããã®ã¯ããã®ãããªã¿ãã«ãããŒãã«ããæžç®ããŠãæ©èœããªãããšã§ããåããµã€ã¬ã³ãSystem.InvalidCastExceptionãçºçããŸãã ãããã£ãŠãlinq to sqlã䜿çšããŠããŒã¿ããŒã¹ã«åææååãä¿åããå Žåã¯ãDbTypeãæå®ããããšãå¿ããªãã§ãã ããã
ã¡ãªã¿ã«ãEntity Frameworkã¯åæåãè¡ã«æ ŒçŽã§ããªãããã䜿çšããããšã決ãããããžã§ã¯ãã§ã¯ãããã¯ã䜿çšããå¿ èŠããããŸããïŒåæåèªäœã解æããåæåãã£ãŒã«ãããšã«è¿œå ã®ã²ãã¿ãŒïŒåæåã®å€ãæ³å®ãããŸãæåååã®ããããã£ã«ä¿åããŸãïŒã
åçæ§ãã¹ã
Linq to sqlã¯ãSQLã§==æŒç®åãšobject.EqualsïŒïŒåŒã³åºãã®äž¡æ¹ããããã³ã°ã§ããŸããããããã³ã°ã«ã¯ããã€ãã®éãããããŸãã
ãã®ããã ActionTemplateãšã³ãã£ãã£ã®ã¯ãšãªã¯ã SystemNameãã£ãŒã«ãã«ãã£ãŠãã£ã«ã¿ãªã³ã°ãããŸãã
var systemName = "SystemName"; var actionTemplate = modelContext.Repositories.Get<ActionTemplateRepository>() .GetActionTemplatesIncludingNonRoot() .FirstOrDefault(at => at.SystemName == systemName);
DECLARE @p0 NVarChar(MAX) = 'SystemName'; SELECT TOP (1) [t0].[Discriminator], [t0].[Id], [t0].[CategoryId], [t0].[Name], [t0].[Type], [t0].[RowVersion], [t0].[SystemName], [t0].[CreationCondition], [t0].[UsageDescription], [t0].[StartDateTimeUtcOverride], [t0].[EndDateTimeUtcOverride], [t0].[DateCreatedUtc], [t0].[DateChangedUtc], [t0].[CreatedById], [t0].[LastChangedById], [t0].[CampaignId], [t0].[MailingTemplateName], [t0].[UseCustomParameters], [t0].[TargetActionTemplateId], [t0].[ParentActionTemplateId], [t0].[IsTransactional], [t0].[MailingStartTime], [t0].[MailingEndTime], [t0].[IgnoreStopLists], [t0].[ReversedActionTemplateId] FROM [directcrm].[ActionTemplates] AS [t0] WHERE [t0].[SystemName] = @p0
ç°åžžãªããšã¯äœããããŸããã ãããã systemNameãnullã®å Žåã¯ã©ãã§ããããïŒ
DECLARE @p0 NVarChar(MAX) = null; SELECT TOP (1) [t0].[Discriminator], [t0].[Id], [t0].[CategoryId], [t0].[Name], [t0].[Type], [t0].[RowVersion], [t0].[SystemName], [t0].[CreationCondition], [t0].[UsageDescription], [t0].[StartDateTimeUtcOverride], [t0].[EndDateTimeUtcOverride], [t0].[DateCreatedUtc], [t0].[DateChangedUtc], [t0].[CreatedById], [t0].[LastChangedById], [t0].[CampaignId], [t0].[MailingTemplateName], [t0].[UseCustomParameters], [t0].[TargetActionTemplateId], [t0].[ParentActionTemplateId], [t0].[IsTransactional], [t0].[MailingStartTime], [t0].[MailingEndTime], [t0].[IgnoreStopLists], [t0].[ReversedActionTemplateId] FROM [directcrm].[ActionTemplates] AS [t0] WHERE [t0].[SystemName] = @p0
æ確ãªããžãã¹ãªã®ã§ãç§ãã¡ã¯äœãè¯ãããšãéæããŸããã object.equalsãè©ŠããŠã¿ãŸãããïŒ
string systemName = null; var actionTemplate = modelContext.Repositories.Get<ActionTemplateRepository>() .GetActionTemplatesIncludingNonRoot() .FirstOrDefault(at => object.Equals(at.SystemName, systemName));
SELECT TOP (1) [t0].[Discriminator], [t0].[Id], [t0].[CategoryId], [t0].[Name], [t0].[Type], [t0].[RowVersion], [t0].[SystemName], [t0].[CreationCondition], [t0].[UsageDescription], [t0].[StartDateTimeUtcOverride], [t0].[EndDateTimeUtcOverride], [t0].[DateCreatedUtc], [t0].[DateChangedUtc], [t0].[CreatedById], [t0].[LastChangedById], [t0].[CampaignId], [t0].[MailingTemplateName], [t0].[UseCustomParameters], [t0].[TargetActionTemplateId], [t0].[ParentActionTemplateId], [t0].[IsTransactional], [t0].[MailingStartTime], [t0].[MailingEndTime], [t0].[IgnoreStopLists], [t0].[ReversedActionTemplateId] FROM [directcrm].[ActionTemplates] AS [t0] WHERE 0 = 1
ç¬åµç
WHERE 0 = 1Linq to sqlã¯ActionTemplate.SystemNameãnullã«ããããšã¯ã§ããªãããšãç¥ã£ãŠãããããã¯ãšãªã圹ã«ç«ããªãããšã瀺ããŠããŸãã Linq to sqlã®ãã®ç¥èãªç¥èã¯ãColumnAttribute.CanBeNullã®å€ãã掟çããŸããã æ®å¿µãªãããDbTypeããã圌ã¯ãããç解ããæ¹æ³ãç¥ããŸããã
å€ãååšããªãåã§ãªã¯ãšã¹ããè¡ãããå ŽåããããŒããã£ã¹ãã¯ãã§ã«äºæãããŠããŸãã
SELECT TOP (1) [t0].[Discriminator], [t0].[Id], [t0].[CategoryId], [t0].[Name], [t0].[Type], [t0].[RowVersion], [t0].[SystemName], [t0].[CreationCondition], [t0].[UsageDescription], [t0].[StartDateTimeUtcOverride], [t0].[EndDateTimeUtcOverride], [t0].[DateCreatedUtc], [t0].[DateChangedUtc], [t0].[CreatedById], [t0].[LastChangedById], [t0].[CampaignId], [t0].[MailingTemplateName], [t0].[UseCustomParameters], [t0].[TargetActionTemplateId], [t0].[ParentActionTemplateId], [t0].[IsTransactional], [t0].[MailingStartTime], [t0].[MailingEndTime], [t0].[IgnoreStopLists], [t0].[ReversedActionTemplateId] FROM [directcrm].[ActionTemplates] AS [t0] WHERE [t0].[SystemName] IS NULL
ãããã£ãŠãæããã«ãçåŒæŒç®åã§ã¯ãªãobject.Equalsã䜿çšããããã«ããŠãã ãããããã¯ãããå®æ§çã«ãå€æãããããã§ãã
LeftOuterJoin
ãåãã®ããã«ãLinqã¯ãã³ã¬ã¯ã·ã§ã³ã®1ã€ã«å€ããªãå¯èœæ§ãããã³ã¬ã¯ã·ã§ã³ãæ¥ç¶ããããã®æ¡åŒµã¡ãœããããŸã£ããæäŸããŠããŸããã ããããæã linq to sqlã§äœæ¥ããå Žåãããšãã°sqlã§å·Šå€éšçµåãååŸããå¿ èŠãããããã®ãããªç¶æ³ã§ã¯linqã¡ãœããã®çµã¿åããã䜿çšããæçµçã«å·Šå€éšçµåã«å€æããŸãã å·Šå€éšçµåãååŸãã2ã€ã®æ¹æ³ãç¥ã£ãŠããŸãã
æåã®ãªãã·ã§ã³ïŒ
CustomerActions .GroupJoin(CustomerBalanceChanges, ca => ca, cbch => cbch.CustomerAction, (ca, cbchs) => cbchs .DefaultIfEmpty() .Select(cbch => new { ca, cbch })) .SelectMany(g => g) .Dump();
2çªç®ã®ãªãã·ã§ã³ïŒ
CustomerActions .SelectMany(ca => CustomerBalanceChanges .Where(cbch => cbch.CustomerAction == ca) .DefaultIfEmpty(), (ca, cbch) => new { ca, cbch}) .Dump();
äž¡æ¹ã®ãªãã·ã§ã³ã¯å®å šã«åäžã®SQLã«å€æãããŸã-ãµãã¯ãšãªãšãã¹ãåã䜿çšããå·Šå€éšçµåïŒãšã³ãã£ãã£ãå³ã»ããããååšãããã©ãããå€æããããïŒïŒ
SELECT [t0].[Id], [t0].[IsTimeKnown], [t0].[BrandName], [t0].[ActionTemplateId], [t0].[CustomerId], [t0].[StaffId], [t0].[PointOfContactId], [t0].[OriginalCustomerId], [t0].[IsOriginalCustomerIdExact], [t0].[TransactionalId], [t0].[DateTimeUtc], [t0].[CreationDateTimeUtc], [t2].[test], [t2].[Id] AS [Id2], [t2].[ChangeAmount], [t2].[Comments], [t2].[CustomerActionId], [t2].[AdminSiteComments], [t2].[BalanceId] FROM [directcrm].[CustomerActions] AS [t0] LEFT OUTER JOIN ( SELECT 1 AS [test], [t1].[Id], [t1].[ChangeAmount], [t1].[Comments], [t1].[CustomerActionId], [t1].[AdminSiteComments], [t1].[BalanceId] FROM [promo].[CustomerBalanceChanges] AS [t1] ) AS [t2] ON [t0].[Id] = [t2].[CustomerActionId]
åç §ïŒCustomerActions-ã·ã¹ãã å ã®æ¶è²»è ã¢ã¯ã·ã§ã³ãCustomerBalanceChanges-æ®é«ã®å€æŽããªã¯ãšã¹ãã«ããã察å¿ããã¢ã¯ã·ã§ã³ïŒãŸãã¯æ®é«å€æŽã¢ã¯ã·ã§ã³ã§ã¯ãªãå Žåã¯ã¢ã¯ã·ã§ã³ïŒã§æ¶è²»è ã®æ®é«ã®å€æŽãååŸããŸãã
ãªã¯ãšã¹ããè€éã«ããŸããããæ¶è²»è ã®ãã©ã³ã¹ã®å€åã ãã§ãªãã圌ãã®è³åãåãåããããšæããŸãã
CustomerActions .SelectMany(ca => CustomerBalanceChanges .Where(cbch => cbch.CustomerAction == ca) .DefaultIfEmpty(), (ca, cbch) => new { ca, cbch}) .SelectMany(cacbch => CustomerPrizes .Where(cp => cacbch.ca == cp.CustomerAction) .DefaultIfEmpty(), (cacbch, cp) => new { cacbch.ca, cacbch.cbch, cp}) .Dump();
SELECT [t0].[Id], [t0].[IsTimeKnown], [t0].[BrandName], [t0].[ActionTemplateId], [t0].[CustomerId], [t0].[StaffId], [t0].[PointOfContactId], [t0].[OriginalCustomerId], [t0].[IsOriginalCustomerIdExact], [t0].[TransactionalId], [t0].[DateTimeUtc], [t0].[CreationDateTimeUtc], [t2].[test], [t2].[Id] AS [Id2], [t2].[ChangeAmount], [t2].[Comments], [t2].[CustomerActionId], [t2].[AdminSiteComments], [t2].[BalanceId], [t4].[test] AS [test2], [t4].[Id] AS [Id3], [t4].[PrizeId], [t4].[SaleFactId], [t4].[PromoMechanicsName], [t4].[WonCustomerPrizeId], [t4].[PrizeType], [t4].[Published], [t4].[PromoMechanicsScheduleItemId], [t4].[CustomerActionId] AS [CustomerActionId2] FROM [directcrm].[CustomerActions] AS [t0] LEFT OUTER JOIN ( SELECT 1 AS [test], [t1].[Id], [t1].[ChangeAmount], [t1].[Comments], [t1].[CustomerActionId], [t1].[AdminSiteComments], [t1].[BalanceId] FROM [promo].[CustomerBalanceChanges] AS [t1] ) AS [t2] ON [t2].[CustomerActionId] = [t0].[Id] LEFT OUTER JOIN ( SELECT 1 AS [test], [t3].[Id], [t3].[PrizeId], [t3].[SaleFactId], [t3].[PromoMechanicsName], [t3].[WonCustomerPrizeId], [t3].[PrizeType], [t3].[Published], [t3].[PromoMechanicsScheduleItemId], [t3].[CustomerActionId] FROM [promo].[CustomerPrizes] AS [t3] ) AS [t4] ON [t0].[Id] = [t4].[CustomerActionId]
æ®éã®ããšã¯äœããããŸãããäºæ³éããå·Šå€éšçµåããã1ã€è¿œå ããŸããã ããããäžè¬çã«èšãã°ãã¯ãšãªãå¥ã®æ¹æ³ã§äœæã§ããŸãã ããšãã°ãè³åããšã«ééããªãæ®é«ã«å€åãããããšãããã£ãŠããããã次ã®ããã«æžãããšãã§ããŸãã
CustomerActions .SelectMany(ca => CustomerPrizes .Join(CustomerBalanceChanges, cp => cp.CustomerAction, cbch => cbch.CustomerAction, (cp, cbch) => new { cbch, cp }) .Where(cbchcp => cbchcp.cbch.CustomerAction == ca) .DefaultIfEmpty(), (ca, cbchcp) => new { cbchcp.cbch, cbchcp.cp, ca}) .Dump();
ããã«ããã次ã®SQLãçæãããŸãã
SELECT [t2].[Id], [t2].[ChangeAmount], [t2].[Comments], [t2].[CustomerActionId], [t2].[AdminSiteComments], [t2].[BalanceId], [t1].[Id] AS [Id2], [t1].[PrizeId], [t1].[SaleFactId], [t1].[PromoMechanicsName], [t1].[WonCustomerPrizeId], [t1].[PrizeType], [t1].[Published], [t1].[PromoMechanicsScheduleItemId], [t1].[CustomerActionId] AS [CustomerActionId2], [t0].[Id] AS [Id3], [t0].[IsTimeKnown], [t0].[BrandName], [t0].[ActionTemplateId], [t0].[CustomerId], [t0].[StaffId], [t0].[PointOfContactId], [t0].[OriginalCustomerId], [t0].[IsOriginalCustomerIdExact], [t0].[TransactionalId], [t0].[DateTimeUtc], [t0].[CreationDateTimeUtc] FROM [directcrm].[CustomerActions] AS [t0] LEFT OUTER JOIN ([promo].[CustomerPrizes] AS [t1] INNER JOIN [promo].[CustomerBalanceChanges] AS [t2] ON [t1].[CustomerActionId] = [t2].[CustomerActionId]) ON [t2].[CustomerActionId] = [t0].[Id]
ãšã³ãã£ãã£ã®ååšã確èªããããã«ããã®SQLã§[ãã¹ã]ãšããŠã®SELECT 1ãæ¶ããããšã«æ³šæããŠãã ããã ãããŠãããã¯ãã®ãããªãªã¯ãšã¹ããæ©èœããªããšããäºå®ã«ã€ãªãããŸããã InvalidOperationExceptionïŒ "NULLã¯ã¡ã³ããŒã«å²ãåœãŠãããšãã§ããŸãããããã¯NULLå€ãèš±å¯ããªãSystem.Int32åã§ãã" linqã¯ãã¹ããã©ã°ã远跡ããªããªã£ããããå€ãNULLã®åããCustomerBalanceChangeããã³CustomerPrizeãšã³ãã£ãã£ãæ£çŽã«äœæããããšããŸãããããšãã°CustomerBalanceChange.Idã«NULLãæžã蟌ãããšã¯ã§ããŸãããããã¯äŸå€ããã¹ãããããããŸãã
ãã®åé¡ã®åé¿çã¯äœã§ããïŒ ãŸããæåã®ã±ãŒã¹ã§æžãããããã«ããªã¯ãšã¹ããèšãæããããšãã§ããŸãã ããããããã¯æ®éçãªè§£æ±ºçã§ã¯ãããŸããã誰ããããã¯ãã€ã§ãã§ãããšèšã£ãããã§ãã Linqã¯æåã®è€éãªãªã¯ãšã¹ãã§ãåãããã«åé¡ã§ããçµåã®åé 眮ã«æéã浪費ããå¿ èŠã¯ãããŸããã ãŸãã2çªç®ã®èŠæ±ã¯æåã®èŠæ±ãšæå³çã«ç°ãªããŸãã
次ã«ããšã³ãã£ãã£ã§ã¯ãªããç¹å®ã®dtoã«å¯ŸããŠãªã¯ãšã¹ããè¡ãããšãã§ããŸããããšãã°ã次ã®ããã«ãªããŸãã
CustomerActions .SelectMany(ca => CustomerPrizes .Join(CustomerBalanceChanges, cp => cp.CustomerAction, cbch => cbch.CustomerAction, (cp, cbch) => new { cbch, cp }) .Where(cbchcp => cbchcp.cbch.CustomerAction == ca) .DefaultIfEmpty(), (ca, cbchcp) => new { cbchcp.cbch, cbchcp.cp, ca}) .Select(cacbchcp => new { CustomerActionId = cacbchcp.ca.Id, CustomerBalanceChangeId = (int?)cacbchcp.cbch.Id, CustomerPrizeId = (int?)cacbchcp.cp.Id, } )
CustomerBalanceChangeIdããã³CustomerPrizeIdã nullå¯èœã«ãªã£ããããåé¡ãããŸããã ãããããã®ãããªã¢ãããŒãã¯ç§ãã¡ã«ã¯é©ããŠããªããããããŸããããªããªãããšã³ãã£ãã£ïŒãšã³ãã£ãã£ã®å€æŽãåé€ããŸãã¯åŒã³åºãïŒãæ£ç¢ºã«å¿ èŠã ããã§ãã ãããã£ãŠãSQLåŽã§nullãã§ãã¯ãè¡ããããçµåã®ç°¡åãª3çªç®ã®æ¹æ³ããããŸãã
CustomerActions .SelectMany(ca => CustomerPrizes .Join(CustomerBalanceChanges, cp => cp.CustomerAction, cbch => cbch.CustomerAction, (cp, cbch) => new { cbch, cp }) .Where(cbchcp => cbchcp.cbch.CustomerAction == ca) .DefaultIfEmpty(), (ca, cbchcp) => new { cbch = cbchcp == null ? null : cbchcp.cbch, cp = cbchcp == null ? null : cbchcp.cp, ca }) .Dump();
ããã¯äžèŠãããšããã»ã©æããªãSQLã«å€æãããŸãã
SELECT (CASE WHEN [t3].[test] IS NULL THEN 1 ELSE 0 END) AS [value], [t3].[Id], [t3].[ChangeAmount], [t3].[Comments], [t3].[CustomerActionId], [t3].[AdminSiteComments], [t3].[BalanceId], [t3].[Id2], [t3].[PrizeId], [t3].[SaleFactId], [t3].[PromoMechanicsName], [t3].[WonCustomerPrizeId], [t3].[PrizeType], [t3].[Published], [t3].[PromoMechanicsScheduleItemId], [t3].[CustomerActionId2], [t0].[Id] AS [Id3], [t0].[IsTimeKnown], [t0].[BrandName], [t0].[ActionTemplateId], [t0].[CustomerId], [t0].[StaffId], [t0].[PointOfContactId], [t0].[OriginalCustomerId], [t0].[IsOriginalCustomerIdExact], [t0].[TransactionalId], [t0].[DateTimeUtc], [t0].[CreationDateTimeUtc] FROM [directcrm].[CustomerActions] AS [t0] LEFT OUTER JOIN ( SELECT 1 AS [test], [t2].[Id], [t2].[ChangeAmount], [t2].[Comments], [t2].[CustomerActionId], [t2].[AdminSiteComments], [t2].[BalanceId], [t1].[Id] AS [Id2], [t1].[PrizeId], [t1].[SaleFactId], [t1].[PromoMechanicsName], [t1].[WonCustomerPrizeId], [t1].[PrizeType], [t1].[Published], [t1].[PromoMechanicsScheduleItemId], [t1].[CustomerActionId] AS [CustomerActionId2] FROM [promo].[CustomerPrizes] AS [t1] INNER JOIN [promo].[CustomerBalanceChanges] AS [t2] ON [t1].[CustomerActionId] = [t2].[CustomerActionId] ) AS [t3] ON [t3].[CustomerActionId] = [t0].[Id]
ããããããªããèŠãããã«ããã¥ã¢ã³ã¹ããããŸãã ã¯ãšãªã¯ããã»ã©è€éã§ã¯ãããŸããã§ããããlint to sqlã¯ãŸã [t3]ãTestã䜿çšãã代ããã«ãæçµéžæã§[ CASE ... WHENæ§æãæç»ããŸããã èŠæ±ã倧ãããããŸã§å¿é ããå¿ èŠã¯ãããŸããã ãããããã®æ¹æ³ã§ããŒãã«10ãçµåããããšãããšãçµæã®SQLã¯ãšãªã¯æ°çŸãããã€ãã«éããå¯èœæ§ããããŸãïŒ æ°çŸãããã€ãã®CASE ... WHENã¹ããŒãã¡ã³ãã
ããã«ãåçŽãªå·Šå€éšçµåã«å¯ŸããŠäžèšã®æ§é ã®ãããããåžžã«äœ¿çšããããšã¯ããã¶ãäžå©ã§ããLeftOuterJoinæ¡åŒµã¡ãœãããèªåã§èšè¿°ããŠã¯ãšãªã§äœ¿çšããæ¹ãã¯ããã«ç°¡åã§ãã ãã®ãããªæ¡åŒµæ©èœãã©ã®ããã«è¡šç€ºããããã次ã«ç€ºããŸãã
public static IQueryable<TResult> LeftOuterJoin<TOuter, TInner, TKey, TResult>( this IQueryable<TOuter> outerValues, IQueryable<TInner> innerValues, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> fullResultSelector, Expression<Func<TOuter, TResult>> partialResultSelector) { Expression<Func<TOuter, IEnumerable<TInner>, IEnumerable<TResult>>> resultSelector = (outerValue, groupedInnerValues) => groupedInnerValues.DefaultIfEmpty().Select( innerValue => Equals(innerValue, default(TInner)) ? partialResultSelector.Evaluate(outerValue) : fullResultSelector.Evaluate(outerValue, innerValue)); return outerValues .GroupJoin(innerValues, outerKeySelector, innerKeySelector, resultSelector.ExpandExpressions()) .SelectMany(result => result); }
ãã®æ¡åŒµæ©èœã¯åžžã«å€æãããŸãããSQLåŽã§nullãã§ãã¯ã䜿çšããŸãã 以äžã®äœ¿çšæ³ãæå³ãããŠããŸãã
var cbchcas = customerActions .LeftOuterJoin( context.Repositories .Get<CustomerBalanceChangeRepository>() .Items .Join(context.Repositories .Get<CustomerPrizeRepository>() .Items, cbch => cbch.CustomerAction, cp => cp.CustomerAction, (cbch, cp) => new { cbch, cp }), ca => ca, cbchcp => cbchcp.cbch.CustomerAction, (ca, cbchcp) => new { ca, cbchcp.cbch, cbchcp.cp }, ca => new { ca, cbch = (CustomerBalanceChange)null, cp = (CustomerPrize)null }) .ToArray();
SELECT (CASE WHEN [t3].[test] IS NULL THEN 1 ELSE 0 END) AS [value], [t3].[Id], [t3].[CustomerActionId], [t3].[ChangeAmount], [t3].[Comments], [t3].[AdminSiteComments], [t3].[BalanceId], [t3].[PrizeType], [t3].[Id2], [t3].[PrizeId], [t3].[PromoMechanicsName] AS [PromoMechanicsSystemName], [t3].[Published], [t3].[PromoMechanicsScheduleItemId], [t3].[SaleFactId], [t3].[CustomerActionId2], [t3].[WonCustomerPrizeId], [t0].[Id] AS [Id3], [t0].[DateTimeUtc], [t0].[IsTimeKnown], [t0].[PointOfContactId], [t0].[BrandName] AS [BrandSystemName], [t0].[CreationDateTimeUtc], [t0].[ActionTemplateId], [t0].[CustomerId], [t0].[StaffId], [t0].[OriginalCustomerId], [t0].[IsOriginalCustomerIdExact], [t0].[TransactionalId] FROM [directcrm].[CustomerActions] AS [t0] LEFT OUTER JOIN ( SELECT 1 AS [test], [t1].[Id], [t1].[CustomerActionId], [t1].[ChangeAmount], [t1].[Comments], [t1].[AdminSiteComments], [t1].[BalanceId], [t2].[PrizeType], [t2].[Id] AS [Id2], [t2].[PrizeId], [t2].[PromoMechanicsName], [t2].[Published], [t2].[PromoMechanicsScheduleItemId], [t2].[SaleFactId], [t2].[CustomerActionId] AS [CustomerActionId2], [t2].[WonCustomerPrizeId] FROM [promo].[CustomerBalanceChanges] AS [t1] INNER JOIN [promo].[CustomerPrizes] AS [t2] ON [t1].[CustomerActionId] = [t2].[CustomerActionId] ) AS [t3] ON [t0].[Id] = [t3].[CustomerActionId]
æ¡åŒµã¡ãœããèªäœãEvaluateããã³ExpandExpressionsã¡ãœããã䜿çšããŠããããšã«æ°ä»ããããããŸããã ãããã¯ã Mindbox.Expressionsã©ã€ãã©ãªã®æ¡åŒµã¡ãœããã§ãã ExpandExpressionsã¡ãœããã¯ãåŒã³åºãããåŒããªãŒå šäœãååž°çã«èµ°æ»ããEvaluateåŒã³åºããEvaluateãåŒã³åºãããåŒã§ååž°çã«çœ®ãæããŸãã ExpandExpressionsã¡ãœããã¯ãExpressionãªããžã§ã¯ããšIQueryableã®äž¡æ¹ã§åŒã³åºãããšãã§ããŸããããã¯ããã䟿å©ãªå ŽåããããŸãïŒããšãã°ãã¯ãšãªãè€æ°ã®å Žæã«æ§ç¯ãããŠããå ŽåïŒã ãã®ã©ã€ãã©ãªã«ã¯ãã³ãŒãã®ãªãã¬ã¯ã·ã§ã³äœæ¥ã®ããã®èå³æ·±ãé¢æ°ãå€æ°ãããŸãã ãããããã©ã€ãã©ãªã¯èª°ãã«åœ¹ç«ã€ã§ãããã
UPDã ååããã®å°ããªã³ã¡ã³ãïŒ
>ãããã£ãŠãæããã«ãçåŒæŒç®åã§ã¯ãªãobject.Equalsã䜿çšããããã«ããŠãã ãããããã¯ããããå®æ§çã«ãå€æãããããã§ãã
æªãã¢ããã€ã¹ã ããã¯ããã¡ãããnullãšæ¯èŒããåé¡ã解決ããŸãã ãã ããå¯äœçšããããŸãã
- äºææ§ã®ãªãåã®å€ã®æ¯èŒãæžãããšãã§ããã³ã³ãã€ã©ã¯èªãããšã¯ãããŸãã
- .NETã§äºåã«èšç®ã§ããªã2ã€ã®å€ïŒããšãã°ããšã³ãã£ãã£ã®2ã€ã®ããããã£ïŒãæ¯èŒãããšãSQLã®å質ãäœäžããé ããªããŸãïŒãŸãã¯çããããäž¡æ¹ãšãnullã§ãïŒ
- åæåã§ã¯æ©èœããªãå ŽåããããŸãã ãããã³ã°ã®ãã°ããããŸã-圌ã¯ãå€ãintã§ã¯ãªãæååã«å€æããå¿ èŠãããããšãåžžã«ç解ããŠããããã§ã¯ãããŸããã 圌ã¯ãæ¯èŒæäœã«ã€ããŠç解ãããã©ã¡ãŒã¿ãŒãobject.Equalsã«æž¡ãããšã«ã€ããŠãåé¡ã«ééããããã§ãã