Skip to content

Commit 20897e3

Browse files
committed
Update to EF10 (CirrusRedOrg#284)
1 parent e7bdd1d commit 20897e3

File tree

47 files changed

+4192
-1596
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4192
-1596
lines changed

src/EFCore.Jet.Data/JetDataReader.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,5 +544,17 @@ public override T GetFieldValue<T>(int ordinal)
544544

545545
return (T)GetValue(ordinal);
546546
}
547+
548+
protected override void Dispose(bool disposing)
549+
{
550+
if (disposing)
551+
{
552+
_wrappedDataReader.Dispose();
553+
}
554+
#if DEBUG
555+
Interlocked.Decrement(ref _activeObjectsCount);
556+
#endif
557+
base.Dispose(disposing);
558+
}
547559
}
548560
}

src/EFCore.Jet/Query/Internal/JetQueryableMethodTranslatingExpressionVisitor.cs

Lines changed: 168 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Diagnostics.CodeAnalysis;
54
using EntityFrameworkCore.Jet.Internal;
5+
using Microsoft.EntityFrameworkCore.Query;
66
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
7+
using System.Diagnostics.CodeAnalysis;
78

89
namespace EntityFrameworkCore.Jet.Query.Internal;
910

@@ -15,6 +16,10 @@ namespace EntityFrameworkCore.Jet.Query.Internal;
1516
/// </summary>
1617
public class JetQueryableMethodTranslatingExpressionVisitor : RelationalQueryableMethodTranslatingExpressionVisitor
1718
{
19+
protected readonly RelationalQueryCompilationContext queryCompilationContext;
20+
21+
private readonly bool _subquery;
22+
1823
/// <summary>
1924
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
2025
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -27,6 +32,8 @@ public JetQueryableMethodTranslatingExpressionVisitor(
2732
RelationalQueryCompilationContext queryCompilationContext)
2833
: base(dependencies, relationalDependencies, queryCompilationContext)
2934
{
35+
this.queryCompilationContext = queryCompilationContext;
36+
_subquery = false;
3037
}
3138

3239
/// <summary>
@@ -39,6 +46,8 @@ protected JetQueryableMethodTranslatingExpressionVisitor(
3946
JetQueryableMethodTranslatingExpressionVisitor parentVisitor)
4047
: base(parentVisitor)
4148
{
49+
this.queryCompilationContext = parentVisitor.queryCompilationContext;
50+
_subquery = true;
4251
}
4352

4453
/// <summary>
@@ -140,9 +149,164 @@ protected override bool IsValidSelectExpressionForExecuteUpdate(
140149
return false;
141150
}
142151

143-
protected override ShapedQueryExpression? TranslateFirstOrDefault(ShapedQueryExpression source, LambdaExpression? predicate,
144-
Type returnType, bool returnDefault)
152+
protected override ShapedQueryExpression? TranslateElementAtOrDefault(
153+
ShapedQueryExpression source,
154+
Expression index,
155+
bool returnDefault)
156+
{
157+
var selectExpression = (SelectExpression)source.QueryExpression;
158+
var translation = TranslateExpression(index);
159+
if (translation == null)
160+
{
161+
return null;
162+
}
163+
164+
if (!IsOrdered(selectExpression))
165+
{
166+
queryCompilationContext.Logger.RowLimitingOperationWithoutOrderByWarning();
167+
}
168+
169+
selectExpression.ApplyOffset(translation);
170+
JetApplyLimit(selectExpression, TranslateExpression(Expression.Constant(1))!);
171+
172+
return source;
173+
}
174+
175+
protected override ShapedQueryExpression? TranslateFirstOrDefault(
176+
ShapedQueryExpression source,
177+
LambdaExpression? predicate,
178+
Type returnType,
179+
bool returnDefault)
180+
{
181+
if (predicate != null)
182+
{
183+
var translatedSource = TranslateWhere(source, predicate);
184+
if (translatedSource == null)
185+
{
186+
return null;
187+
}
188+
189+
source = translatedSource;
190+
}
191+
192+
var selectExpression = (SelectExpression)source.QueryExpression;
193+
if (selectExpression.Predicate == null
194+
&& selectExpression.Orderings.Count == 0)
195+
{
196+
queryCompilationContext.Logger.FirstWithoutOrderByAndFilterWarning();
197+
}
198+
199+
JetApplyLimit(selectExpression, TranslateExpression(Expression.Constant(1))!);
200+
201+
return source.ShaperExpression.Type != returnType
202+
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType))
203+
: source;
204+
}
205+
206+
protected override ShapedQueryExpression? TranslateLastOrDefault(
207+
ShapedQueryExpression source,
208+
LambdaExpression? predicate,
209+
Type returnType,
210+
bool returnDefault)
211+
{
212+
var selectExpression = (SelectExpression)source.QueryExpression;
213+
if (selectExpression.Orderings.Count == 0)
214+
{
215+
throw new InvalidOperationException(
216+
RelationalStrings.LastUsedWithoutOrderBy(returnDefault ? nameof(Queryable.LastOrDefault) : nameof(Queryable.Last)));
217+
}
218+
219+
if (predicate != null)
220+
{
221+
var translatedSource = TranslateWhere(source, predicate);
222+
if (translatedSource == null)
223+
{
224+
return null;
225+
}
226+
227+
source = translatedSource;
228+
}
229+
230+
selectExpression.ReverseOrderings();
231+
JetApplyLimit(selectExpression, TranslateExpression(Expression.Constant(1))!);
232+
233+
return source.ShaperExpression.Type != returnType
234+
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType))
235+
: source;
236+
}
237+
238+
protected override ShapedQueryExpression? TranslateSingleOrDefault(
239+
ShapedQueryExpression source,
240+
LambdaExpression? predicate,
241+
Type returnType,
242+
bool returnDefault)
145243
{
146-
return base.TranslateFirstOrDefault(source, predicate, returnType, returnDefault);
244+
if (predicate != null)
245+
{
246+
var translatedSource = TranslateWhere(source, predicate);
247+
if (translatedSource == null)
248+
{
249+
return null;
250+
}
251+
252+
source = translatedSource;
253+
}
254+
255+
var selectExpression = (SelectExpression)source.QueryExpression;
256+
JetApplyLimit(selectExpression, TranslateExpression(Expression.Constant(_subquery ? 1 : 2))!);
257+
258+
return source.ShaperExpression.Type != returnType
259+
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType))
260+
: source;
147261
}
262+
263+
protected override ShapedQueryExpression? TranslateTake(ShapedQueryExpression source, Expression count)
264+
{
265+
var selectExpression = (SelectExpression)source.QueryExpression;
266+
var translation = TranslateExpression(count);
267+
if (translation == null)
268+
{
269+
return null;
270+
}
271+
272+
if (!IsOrdered(selectExpression))
273+
{
274+
queryCompilationContext.Logger.RowLimitingOperationWithoutOrderByWarning();
275+
}
276+
277+
JetApplyLimit(selectExpression, translation);
278+
279+
return source;
280+
}
281+
282+
private void JetApplyLimit(SelectExpression selectExpression, SqlExpression limit)
283+
{
284+
var oldLimit = selectExpression.Limit;
285+
286+
if (oldLimit is null)
287+
{
288+
selectExpression.SetLimit(limit);
289+
return;
290+
}
291+
292+
if (oldLimit is SqlConstantExpression { Value: int oldConst } && limit is SqlConstantExpression { Value: int newConst })
293+
{
294+
// if both the old and new limit are constants, use the smaller one
295+
// (aka constant-fold LEAST(constA, constB))
296+
if (oldConst > newConst)
297+
{
298+
selectExpression.SetLimit(limit);
299+
}
300+
301+
return;
302+
}
303+
304+
if (oldLimit.Equals(limit))
305+
{
306+
return;
307+
}
308+
309+
selectExpression.ApplyLimit(limit);
310+
}
311+
148312
}

test/EFCore.Jet.FunctionalTests/GraphUpdates/GraphUpdatesJetTestBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ protected override async Task SeedAsync(PoolableDbContext context)
230230
await context.Database.ExecuteSqlAsync($"ALTER TABLE `OwnedOptional2` DROP CONSTRAINT `FK_OwnedOptional2_OwnedOptional1_OwnedOptional1OwnerRootId_Owne~`");
231231
await context.Database.ExecuteSqlAsync($"ALTER TABLE `OwnedRequired2` DROP CONSTRAINT `FK_OwnedRequired2_OwnedRequired1_OwnedRequired1OwnerRootId_Owne~`");
232232
await context.Database.ExecuteSqlAsync($"ALTER TABLE `RequiredComposite2` DROP CONSTRAINT `FK_RequiredComposite2_RequiredAk1_ParentId_ParentAlternateId`");
233+
await context.Database.ExecuteSqlAsync($"ALTER TABLE `SharedFkParent` DROP CONSTRAINT `FK_SharedFkParent_SharedFkDependant_RootId_DependantId`");
233234
}
234235
}
235236
}

test/EFCore.Jet.FunctionalTests/GraphUpdates/ProxyGraphUpdatesJetTest.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
3232
modelBuilder.Entity<SharedFkParent>().Property(x => x.Id).HasColumnType("int");
3333
}
3434

35-
protected override Task SeedAsync(DbContext context)
35+
protected override async Task SeedAsync(DbContext context)
3636
{
3737
//context.Database.ExecuteSql($"ALTER TABLE `SharedFkDependant` DROP CONSTRAINT `AK_SharedFkDependant_RootId_Id`");
38-
return base.SeedAsync(context);
38+
await base.SeedAsync(context);
39+
40+
await context.Database.ExecuteSqlAsync($"ALTER TABLE `OptionalComposite2` DROP CONSTRAINT `FK_OptionalComposite2_OptionalAk1_ParentId_ParentAlternateId`");
41+
//await context.Database.ExecuteSqlAsync($"ALTER TABLE `OptionalOverlapping2` DROP CONSTRAINT `FK_OptionalOverlapping2_RequiredComposite1_ParentId_ParentAlter~`");
42+
await context.Database.ExecuteSqlAsync($"ALTER TABLE `OptionalSingleComposite2` DROP CONSTRAINT `FK_OptionalSingleComposite2_OptionalSingleAk1_BackId_ParentAlte~`");
43+
//await context.Database.ExecuteSqlAsync($"ALTER TABLE `RequiredComposite2` DROP CONSTRAINT `FK_RequiredComposite2_RequiredAk1_ParentId_ParentAlternateId`");
44+
await context.Database.ExecuteSqlAsync($"ALTER TABLE `SharedFkParent` DROP CONSTRAINT `FK_SharedFkParent_SharedFkDependant_RootId_DependantId`");
3945
}
4046
}
4147
}

0 commit comments

Comments
 (0)