Skip to content

Commit

Permalink
Query: Find correct table to use when owned entity is mapped to diffe…
Browse files Browse the repository at this point in the history
…rent table

Resolves #2340
  • Loading branch information
smitpatel committed Sep 4, 2020
1 parent 58cc57a commit b6ca9f5
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1375,7 +1375,6 @@ private Expression TryExpand(Expression source, MemberIdentity member)
{
// Owned types don't support inheritance See https://github.com/dotnet/efcore/issues/9630
// So there is no handling for dependent having TPT

// If navigation is defined on derived type and entity type is part of TPT then we need to get ITableBase for derived type.
// TODO: The following code should also handle Function and SqlQuery mappings
var table = navigation.DeclaringEntityType.BaseType == null
Expand Down Expand Up @@ -1406,9 +1405,13 @@ private Expression TryExpand(Expression source, MemberIdentity member)
}
}

// InnerShaper is still null if either it is not table sharing or we failed to find table to pick data from
if (innerShaper == null)
{
// InnerShaper is still null if either it is not table sharing or we failed to find table to pick data from
// So we find the table it is mapped to and generate join with it.
// Owned types don't support inheritance See https://github.com/dotnet/efcore/issues/9630
// So there is no handling for dependent having TPT
table = targetEntityType.GetViewOrTableMappings().Single().Table;
var innerSelectExpression = _sqlExpressionFactory.Select(targetEntityType);
var innerShapedQuery = CreateShapedQueryExpression(targetEntityType, innerSelectExpression);

Expand Down
127 changes: 126 additions & 1 deletion test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8684,7 +8684,7 @@ private SqlServerTestStore CreateDatabase14911()

#endregion

#region Issue14911
#region Issue15215

[ConditionalFact]
public virtual void Repeated_parameters_in_generated_query_sql()
Expand Down Expand Up @@ -8784,6 +8784,131 @@ private SqlServerTestStore CreateDatabase15215()

#endregion

#region Issue22340

[ConditionalFact]
public virtual void Owned_entity_mapped_to_separate_table()
{
using (CreateDatabase22340())
{
using var context = new MyContext22340(_options);

var masterTrunk = context.MasterTrunk.OrderBy(e => EF.Property<string>(e, "Id")).FirstOrDefault(); //exception Sequence contains no elements.

Assert.NotNull(masterTrunk);

AssertSql(
@"SELECT [t].[Id], [t].[MasterTrunk22340Id], [t].[MasterTrunk22340Id0], [f0].[CurrencyBag22340MasterTrunk22340Id], [f0].[Id], [f0].[Amount], [f0].[Code], [s0].[CurrencyBag22340MasterTrunk22340Id], [s0].[Id], [s0].[Amount], [s0].[Code]
FROM (
SELECT TOP(1) [m].[Id], [f].[MasterTrunk22340Id], [s].[MasterTrunk22340Id] AS [MasterTrunk22340Id0]
FROM [MasterTrunk] AS [m]
LEFT JOIN [FungibleBag] AS [f] ON [m].[Id] = [f].[MasterTrunk22340Id]
LEFT JOIN [StaticBag] AS [s] ON [m].[Id] = [s].[MasterTrunk22340Id]
ORDER BY [m].[Id]
) AS [t]
LEFT JOIN [FungibleBag_Currencies] AS [f0] ON [t].[MasterTrunk22340Id] = [f0].[CurrencyBag22340MasterTrunk22340Id]
LEFT JOIN [StaticBag_Currencies] AS [s0] ON [t].[MasterTrunk22340Id0] = [s0].[CurrencyBag22340MasterTrunk22340Id]
ORDER BY [t].[Id], [t].[MasterTrunk22340Id], [t].[MasterTrunk22340Id0], [f0].[CurrencyBag22340MasterTrunk22340Id], [f0].[Id], [s0].[CurrencyBag22340MasterTrunk22340Id], [s0].[Id]");
}
}

private class MasterTrunk22340
{
public CurrencyBag22340 FungibleBag { get; set; }
public CurrencyBag22340 StaticBag { get; set; }
}

private class CurrencyBag22340
{
public IEnumerable<Currency22340> Currencies { get; set; }
}

private class Currency22340
{
[Column(TypeName = "decimal(18,2)")]
public decimal Amount { get; set; }
[Column(TypeName = "decimal(18,2)")]
public decimal Code { get; set; }
}

private class MyContext22340 : DbContext
{
public MyContext22340(DbContextOptions options)
: base(options)
{
}

public DbSet<MasterTrunk22340> MasterTrunk { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var builder = modelBuilder.Entity<MasterTrunk22340>();
builder.Property<string>("Id").ValueGeneratedOnAdd();
builder.HasKey("Id");

builder.OwnsOne(p => p.FungibleBag, p =>
{
p.OwnsMany(p => p.Currencies, p =>
{
p.Property(p => p.Amount).IsConcurrencyToken();
});

p.ToTable("FungibleBag");
});


builder.OwnsOne(p => p.StaticBag, p =>
{
p.OwnsMany(p => p.Currencies, p =>
{
p.Property(p => p.Amount).IsConcurrencyToken();
});
p.ToTable("StaticBag");
});
}
}

private SqlServerTestStore CreateDatabase22340()
=> CreateTestStore(
() => new MyContext22340(_options),
context =>
{
var masterTrunk = new MasterTrunk22340()
{
FungibleBag = new CurrencyBag22340()
{
Currencies = new Currency22340[]
{
new Currency22340()
{
Amount = 10,
Code = 999
}

}
},
StaticBag = new CurrencyBag22340()
{
Currencies = new Currency22340[]
{
new Currency22340()
{
Amount = 555,
Code = 111
}

}
}
};
context.Add(masterTrunk);

context.SaveChanges();

ClearLog();
});

#endregion

private DbContextOptions _options;

private SqlServerTestStore CreateTestStore<TContext>(
Expand Down

0 comments on commit b6ca9f5

Please sign in to comment.