1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Query.LinqToEntities
{
using System.Data.Entity.TestModels.ArubaModel;
using System.Linq;
using Xunit;
public class DefaultIfEmptyTests : FunctionalTestBase
{
[Fact]
public void SelectMany_with_DefaultIfEmpty_translates_into_left_outer_join()
{
using (var context = new ArubaContext())
{
var expectedSql =
@"SELECT
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1],
[Extent2].[Number] AS [Number],
[Extent2].[Comment] AS [Comment],
[Extent2].[Resolution] AS [Resolution],
[Extent2].[Failure_Id] AS [Failure_Id],
[Extent2].[ArubaOwner_Id] AS [ArubaOwner_Id]
FROM [dbo].[ArubaOwners] AS [Extent1]
LEFT OUTER JOIN [dbo].[ArubaBugs] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ArubaOwner_Id]";
var query = context.Owners.SelectMany(c => c.Bugs.DefaultIfEmpty());
QueryTestHelpers.VerifyDbQuery(query, expectedSql);
// verify that owners that have empty collecion of bugs are projected as nulls
var results = query.ToList();
var ownersWithoutBugsCount = context.Owners.Count(o => !o.Bugs.Any());
Assert.Equal(ownersWithoutBugsCount, results.Count(r => r == null));
}
}
[Fact]
public void DefaultIfEmpty_with_null_default()
{
using (var context = new ArubaContext())
{
var expectedSql =
@"SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Alias] AS [Alias],
[Extent2].[Id] AS [Id1],
[Extent2].[Number] AS [Number],
[Extent2].[Comment] AS [Comment],
[Extent2].[Resolution] AS [Resolution],
[Extent2].[Failure_Id] AS [Failure_Id],
[Extent2].[ArubaOwner_Id] AS [ArubaOwner_Id]
FROM [dbo].[ArubaOwners] AS [Extent1]
LEFT OUTER JOIN [dbo].[ArubaBugs] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[ArubaOwner_Id]) AND (1 = [Extent2].[Id])";
var query = context.Owners.SelectMany(c => c.Bugs.Where(b => b.Id == 1).DefaultIfEmpty(), (o, b) => new { o, b });
QueryTestHelpers.VerifyDbQuery(query, expectedSql);
// verify that all owners are projected
// verify that the only bug that is non-null has Id = 1
var results = query.ToList();
var ownersCount = context.Owners.Count();
Assert.Equal(ownersCount, results.Select(r => r.o.Id).Distinct().Count());
for (int i = 0; i < ownersCount; i++)
{
var bug = results[i].b;
Assert.True(bug == null || bug.Id == 1);
}
}
}
[Fact]
public void DefaultIfEmpty_with_non_null_default()
{
using (var context = new ArubaContext())
{
var expectedSql =
@"SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Alias] AS [Alias],
CASE WHEN (CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS tinyint) ELSE cast(1 as tinyint) END IS NULL) THEN 0 ELSE [Extent2].[Id] END AS [C1]
FROM [dbo].[ArubaOwners] AS [Extent1]
LEFT OUTER JOIN [dbo].[ArubaBugs] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[ArubaOwner_Id]) AND (1 = [Extent2].[Id])";
var query = context.Owners.SelectMany(c => c.Bugs.Where(b => b.Id == 1).Select(b => b.Id).DefaultIfEmpty(), (o, b) => new { o, b });
QueryTestHelpers.VerifyDbQuery(query, expectedSql);
// verify that all owners are projected
// verify that the only bug that is non 0 has Id = 1
var results = query.ToList();
var ownersCount = context.Owners.Count();
Assert.Equal(ownersCount, results.Select(r => r.o.Id).Distinct().Count());
for (int i = 0; i < ownersCount; i++)
{
var bugId = results[i].b;
Assert.True(bugId == 0 || bugId == 1);
}
}
}
[Fact]
public void DefaultIfEmpty_with_explicit_default()
{
using (var context = new ArubaContext())
{
var expectedSql =
@"SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Alias] AS [Alias],
CASE WHEN (CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS tinyint) ELSE cast(1 as tinyint) END IS NULL) THEN N'Foo' ELSE [Extent2].[Comment] END AS [C1]
FROM [dbo].[ArubaOwners] AS [Extent1]
LEFT OUTER JOIN [dbo].[ArubaBugs] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[ArubaOwner_Id]) AND (1 = [Extent2].[Id])";
var query = context.Owners.SelectMany(o => o.Bugs.Where(b => b.Id == 1).Select(b => b.Comment).DefaultIfEmpty("Foo"), (o, b) => new { o, b });
QueryTestHelpers.VerifyDbQuery(query, expectedSql);
// verify that all owners are projected
// verify that the only bug that is non "Foo" has Id = 1
var results = query.ToList();
var bugCommentForIdOne = context.Bugs.Where(b => b.Id == 1).Single().Comment;
var ownersCount = context.Owners.Count();
Assert.Equal(ownersCount, results.Select(r => r.o.Id).Distinct().Count());
for (int i = 0; i < ownersCount; i++)
{
var bugComment = results[i].b;
Assert.True(bugComment == "Foo" || bugComment == bugCommentForIdOne);
}
}
}
[Fact]
public void DefaultIfEmpty_with_anonymous_type_default()
{
using (var context = new ArubaContext())
{
var expectedSql =
@"SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Alias] AS [Alias],
CASE WHEN (CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS tinyint) ELSE cast(1 as tinyint) END IS NULL) THEN -1 ELSE [Extent2].[Id] END AS [C1],
CASE WHEN (CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS tinyint) ELSE cast(1 as tinyint) END IS NULL) THEN N'Unknown' ELSE [Extent2].[Comment] END AS [C2],
CASE WHEN (CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS tinyint) ELSE cast(1 as tinyint) END IS NULL) THEN 3 ELSE [Extent2].[Resolution] END AS [C3]
FROM [dbo].[ArubaOwners] AS [Extent1]
LEFT OUTER JOIN [dbo].[ArubaBugs] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[ArubaOwner_Id]) AND (5 = [Extent2].[Id])";
var query = context.Owners.SelectMany(o => o.Bugs.Where(b => b.Id == 5).Select(b => new { b.Id, b.Comment, b.Resolution }).DefaultIfEmpty(new { Id = -1, Comment = "Unknown", Resolution = (ArubaBugResolution?)ArubaBugResolution.NoRepro }), (o, b) => new { o, b });
QueryTestHelpers.VerifyDbQuery(query, expectedSql);
// verify that all owners are projected
// verify that the only bug that is non default has Id = 5
var results = query.ToList();
var bugCommentForIdFive = context.Bugs.Where(b => b.Id == 5).Single().Comment;
var bugResolutionForIdFive = context.Bugs.Where(b => b.Id == 5).Single().Resolution;
var ownersCount = context.Owners.Count();
Assert.Equal(ownersCount, results.Select(r => r.o.Id).Distinct().Count());
for (int i = 0; i < ownersCount; i++)
{
var bug = results[i].b;
Assert.True(bug.Id == -1 || bug.Id == 5);
Assert.True(bug.Comment == "Unknown" || bug.Comment == bugCommentForIdFive);
Assert.True(bug.Resolution == ArubaBugResolution.NoRepro || bug.Resolution == bugResolutionForIdFive);
}
}
}
[Fact]
public void SelectMany_of_two_entity_sets_withDefaultIfEmpty_translated_to_left_outer_join()
{
using (var context = new ArubaContext())
{
var expectedSql =
@"SELECT
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1],
[Extent2].[Number] AS [Number],
[Extent2].[Comment] AS [Comment],
[Extent2].[Resolution] AS [Resolution],
[Extent2].[Failure_Id] AS [Failure_Id],
[Extent2].[ArubaOwner_Id] AS [ArubaOwner_Id]
FROM [dbo].[ArubaFailures] AS [Extent1]
LEFT OUTER JOIN [dbo].[ArubaBugs] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Failure_Id]
WHERE [Extent1].[Discriminator] IN (N'ArubaBaseline',N'ArubaTestFailure',N'ArubaFailure')";
var query = context.Failures.GroupJoin(context.Bugs, f => f.Id, b => b.Failure.Id, (f, b) => new { f, b }).SelectMany(r => r.b.DefaultIfEmpty());
QueryTestHelpers.VerifyDbQuery(query, expectedSql);
// verify that failures that have empty collecion of bugs are projected as nulls
var results = query.ToList();
var failuresWithoutBugsCount = context.Failures.Count(o => !o.Bugs.Any());
Assert.Equal(failuresWithoutBugsCount, results.Count(r => r == null));
}
}
}
}
|