Skip to content

Commit 15f5a2c

Browse files
committed
Changes following review by Shay.
1 parent f57e7b7 commit 15f5a2c

37 files changed

+199
-172
lines changed

src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs

+27-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ protected virtual void ValidateIndexes(
460460
{
461461
foreach (var entityType in model.GetEntityTypes())
462462
{
463-
foreach (var index in entityType.GetIndexes())
463+
foreach (var index in entityType.GetDeclaredIndexes())
464464
{
465465
if (index.FindAnnotation(CosmosAnnotationNames.VectorIndexType) != null)
466466
{
@@ -483,4 +483,30 @@ protected virtual void ValidateIndexes(
483483
}
484484
}
485485
}
486+
487+
/// <summary>
488+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
489+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
490+
/// any release. You should only use it directly in your code with extreme caution and knowing that
491+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
492+
/// </summary>
493+
protected override void ValidatePropertyMapping(
494+
IModel model,
495+
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
496+
{
497+
base.ValidatePropertyMapping(model, logger);
498+
499+
foreach (var entityType in model.GetEntityTypes())
500+
{
501+
foreach (var property in entityType.GetDeclaredProperties())
502+
{
503+
var cosmosVectorType = property.GetVectorType();
504+
if (cosmosVectorType is { DataType: null })
505+
{
506+
// Will throw if the data type is not set and cannot be inferred.
507+
CosmosVectorType.CreateDefaultVectorDataType(property.GetValueConverter()?.ProviderClrType ?? property.ClrType);
508+
}
509+
}
510+
}
511+
}
486512
}

src/EFCore.Cosmos/Metadata/Internal/CosmosVectorType.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
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 Microsoft.EntityFrameworkCore.Cosmos.Internal;
5+
46
namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
57

68
/// <summary>
@@ -26,6 +28,8 @@ public static VectorDataType CreateDefaultVectorDataType(Type clrType)
2628
? VectorDataType.Uint8
2729
: elementType == typeof(Half)
2830
? VectorDataType.Float16
29-
: VectorDataType.Float32;
31+
: elementType == typeof(float)
32+
? VectorDataType.Float32
33+
: throw new InvalidOperationException(CosmosStrings.BadVectorDataType(clrType.ShortDisplayName()));
3034
}
3135
}

src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/EFCore.Cosmos/Properties/CosmosStrings.resx

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@
120120
<data name="AnalyticalTTLMismatch" xml:space="preserve">
121121
<value>The time to live for analytical store was configured to '{ttl1}' on '{entityType1}', but on '{entityType2}' it was configured to '{ttl2}'. All entity types mapped to the same container '{container}' must be configured with the same time to live for analytical store.</value>
122122
</data>
123-
<data name="ArgumentNotConstant" xml:space="preserve">
124-
<value>The '{parameter}' value passed to '{methodName}' must be a constant.</value>
123+
<data name="BadVectorDataType" xml:space="preserve">
124+
<value>The type '{clrType}' is being used as a vector, but the vector data type cannot be inferred. Either use a collection of a supported type such as 'byte', 'sbyte', 'float', or 'Half', or specify the data type explicitly.</value>
125125
</data>
126126
<data name="CanConnectNotSupported" xml:space="preserve">
127127
<value>The Cosmos database does not support 'CanConnect' or 'CanConnectAsync'.</value>
@@ -319,7 +319,7 @@
319319
<value>A vector index is defined for `{entityType}.{property}`, but this property has not been configured as a vector. Use 'IsVector()' in 'OnModelCreating' to configure the property as a vector.</value>
320320
</data>
321321
<data name="VectorSearchRequiresVector" xml:space="preserve">
322-
<value>The 'VectorDistance' function can only be used with a property mapped as a vectors. Use 'IsVector()' in 'OnModelCreating' to configure the property as a vector.</value>
322+
<value>The 'VectorDistance' function can only be used with a property mapped as a vector. Use 'IsVector()' in 'OnModelCreating' to configure the property as a vector.</value>
323323
</data>
324324
<data name="VisitChildrenMustBeOverridden" xml:space="preserve">
325325
<value>'VisitChildren' must be overridden in the class deriving from 'SqlExpression'.</value>

src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs

+7-9
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
using Microsoft.EntityFrameworkCore.Cosmos.Internal;
55
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
6-
using Newtonsoft.Json;
7-
using Newtonsoft.Json.Linq;
86

97
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
108

@@ -352,9 +350,9 @@ when _parameterValues.TryGetValue(parameterExpression.Name, out var parameterVal
352350
for (var i = 0; i < constantValues.Length; i++)
353351
{
354352
var value = constantValues[i];
355-
var typeMapping = (CosmosTypeMapping?)typeMappingSource.FindMapping(value.GetType());
353+
var typeMapping = typeMappingSource.FindMapping(value.GetType());
356354
Check.DebugAssert(typeMapping is not null, "Could not find type mapping for FromSql parameter");
357-
substitutions[i] = typeMapping.GenerateConstant(value);
355+
substitutions[i] = ((CosmosTypeMapping)typeMapping).GenerateConstant(value);
358356
}
359357

360358
break;
@@ -540,7 +538,7 @@ private void GenerateList<T>(
540538
protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression)
541539
{
542540
Check.DebugAssert(sqlConstantExpression.TypeMapping is not null, "SqlConstantExpression without a type mapping");
543-
_sqlBuilder.Append(sqlConstantExpression.TypeMapping.GenerateConstant(sqlConstantExpression.Value));
541+
_sqlBuilder.Append(((CosmosTypeMapping)sqlConstantExpression.TypeMapping).GenerateConstant(sqlConstantExpression.Value));
544542

545543
return sqlConstantExpression;
546544
}
@@ -551,11 +549,11 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant
551549
/// any release. You should only use it directly in your code with extreme caution and knowing that
552550
/// doing so can result in application failures when updating to a new Entity Framework Core release.
553551
/// </summary>
554-
protected override Expression VisitJsonFragment(JsonFragmentExpression jsonFragmentExpression)
552+
protected override Expression VisitFragment(FragmentExpression fragmentExpression)
555553
{
556-
_sqlBuilder.Append(jsonFragmentExpression.Json);
554+
_sqlBuilder.Append(fragmentExpression.Fragment);
557555

558-
return jsonFragmentExpression;
556+
return fragmentExpression;
559557
}
560558

561559
/// <summary>
@@ -590,7 +588,7 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame
590588
if (_sqlParameters.All(sp => sp.Name != parameterName))
591589
{
592590
Check.DebugAssert(sqlParameterExpression.TypeMapping is not null, "SqlParameterExpression without a type mapping");
593-
var jToken = sqlParameterExpression.TypeMapping.GenerateJToken(_parameterValues[sqlParameterExpression.Name]);
591+
var jToken = ((CosmosTypeMapping)sqlParameterExpression.TypeMapping).GenerateJToken(_parameterValues[sqlParameterExpression.Name]);
594592
_sqlParameters.Add(new SqlParameter(parameterName, jToken));
595593
}
596594

src/EFCore.Cosmos/Query/Internal/CosmosQueryUtils.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Diagnostics.CodeAnalysis;
5-
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
65

76
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
87

@@ -56,7 +55,7 @@ public static bool TryConvertToArray(
5655
var arrayClrType = projection.Type.MakeArrayType();
5756
// TODO: Temporary hack - need to perform proper derivation of the array type mapping from the element (e.g. for
5857
// value conversion).
59-
var arrayTypeMapping = (CosmosTypeMapping?)typeMappingSource.FindMapping(arrayClrType);
58+
var arrayTypeMapping = typeMappingSource.FindMapping(arrayClrType);
6059

6160
array = new ArrayExpression(subquery, arrayClrType, arrayTypeMapping);
6261
return true;

src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Diagnostics.CodeAnalysis;
55
using Microsoft.EntityFrameworkCore.Cosmos.Internal;
66
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;
7-
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
87

98
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
109

@@ -1378,7 +1377,7 @@ when methodCallExpression.TryGetIndexerArguments(_queryCompilationContext.Model,
13781377
&& WrapPrimitiveCollectionAsShapedQuery(
13791378
sqlExpression,
13801379
sqlExpression.Type.GetSequenceType(),
1381-
(CosmosTypeMapping?)sqlExpression.TypeMapping!.ElementTypeMapping!) is { } primitiveCollectionTranslation)
1380+
sqlExpression.TypeMapping!.ElementTypeMapping!) is { } primitiveCollectionTranslation)
13821381
{
13831382
return primitiveCollectionTranslation;
13841383
}
@@ -1414,8 +1413,8 @@ when methodCallExpression.TryGetIndexerArguments(_queryCompilationContext.Model,
14141413
// TODO: The following currently just gets the type mapping from the CLR type, which ignores e.g. value converters on
14151414
// TODO: properties compared against
14161415
var elementClrType = inlineQueryRootExpression.ElementType;
1417-
var elementTypeMapping = (CosmosTypeMapping?)_typeMappingSource.FindMapping(elementClrType)!;
1418-
var arrayTypeMapping = (CosmosTypeMapping?)_typeMappingSource.FindMapping(elementClrType.MakeArrayType()); // TODO: IEnumerable?
1416+
var elementTypeMapping = _typeMappingSource.FindMapping(elementClrType)!;
1417+
var arrayTypeMapping = _typeMappingSource.FindMapping(elementClrType.MakeArrayType()); // TODO: IEnumerable?
14191418
var inlineArray = new ArrayConstantExpression(elementClrType, translatedItems, arrayTypeMapping);
14201419

14211420
// Unfortunately, Cosmos doesn't support selecting directly from an inline array: SELECT i FROM i IN [1,2,3] (syntax error)
@@ -1450,8 +1449,8 @@ [new ProjectionExpression(inlineArray, null!)],
14501449
// TODO: The following currently just gets the type mapping from the CLR type, which ignores e.g. value converters on
14511450
// TODO: properties compared against
14521451
var elementClrType = parameterQueryRootExpression.ElementType;
1453-
var arrayTypeMapping = (CosmosTypeMapping?)_typeMappingSource.FindMapping(elementClrType.MakeArrayType()); // TODO: IEnumerable?
1454-
var elementTypeMapping = (CosmosTypeMapping?)_typeMappingSource.FindMapping(elementClrType)!;
1452+
var arrayTypeMapping = _typeMappingSource.FindMapping(elementClrType.MakeArrayType()); // TODO: IEnumerable?
1453+
var elementTypeMapping = _typeMappingSource.FindMapping(elementClrType)!;
14551454
var sqlParameterExpression = new SqlParameterExpression(parameterQueryRootExpression.ParameterExpression, arrayTypeMapping);
14561455

14571456
// Unfortunately, Cosmos doesn't support selecting directly from an inline array: SELECT i FROM i IN [1,2,3] (syntax error)
@@ -1470,7 +1469,7 @@ [new ProjectionExpression(sqlParameterExpression, null!)],
14701469
private ShapedQueryExpression WrapPrimitiveCollectionAsShapedQuery(
14711470
Expression array,
14721471
Type elementClrType,
1473-
CosmosTypeMapping elementTypeMapping)
1472+
CoreTypeMapping elementTypeMapping)
14741473
{
14751474
// TODO: Do proper alias management: #33894
14761475
var select = SelectExpression.CreateForPrimitiveCollection(

src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ private Expression CreateGetValueExpression(
653653
&& !property.IsShadowProperty())
654654
{
655655
var readExpression = CreateGetValueExpression(
656-
jObjectExpression, storeName, type.MakeNullable(), (CosmosTypeMapping)property.GetTypeMapping());
656+
jObjectExpression, storeName, type.MakeNullable(), property.GetTypeMapping());
657657

658658
var nonNullReadExpression = readExpression;
659659
if (nonNullReadExpression.Type != type)
@@ -674,15 +674,15 @@ private Expression CreateGetValueExpression(
674674
}
675675

676676
return Convert(
677-
CreateGetValueExpression(jObjectExpression, storeName, type.MakeNullable(), (CosmosTypeMapping)property.GetTypeMapping()),
677+
CreateGetValueExpression(jObjectExpression, storeName, type.MakeNullable(), property.GetTypeMapping()),
678678
type);
679679
}
680680

681681
private Expression CreateGetValueExpression(
682682
Expression jObjectExpression,
683683
string storeName,
684684
Type type,
685-
CosmosTypeMapping typeMapping = null)
685+
CoreTypeMapping typeMapping = null)
686686
{
687687
Check.DebugAssert(type.IsNullableType(), "Must read nullable type from JObject.");
688688

src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Collections;
55
using System.Diagnostics.CodeAnalysis;
66
using Microsoft.EntityFrameworkCore.Cosmos.Internal;
7-
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
87

98
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
109

@@ -771,7 +770,7 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio
771770
translatedItems[i] = translatedItem;
772771
}
773772

774-
var arrayTypeMapping = (CosmosTypeMapping?)typeMappingSource.FindMapping(newArrayExpression.Type);
773+
var arrayTypeMapping = typeMappingSource.FindMapping(newArrayExpression.Type);
775774
var elementClrType = newArrayExpression.Type.GetElementType()!;
776775
var inlineArray = new ArrayConstantExpression(elementClrType, translatedItems, arrayTypeMapping);
777776

src/EFCore.Cosmos/Query/Internal/ExpressionExtensions.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
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 Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
5-
64
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
75

86
/// <summary>
@@ -19,7 +17,7 @@ public static class ExpressionExtensions
1917
/// any release. You should only use it directly in your code with extreme caution and knowing that
2018
/// doing so can result in application failures when updating to a new Entity Framework Core release.
2119
/// </summary>
22-
public static CosmosTypeMapping? InferTypeMapping(params Expression[] expressions)
20+
public static CoreTypeMapping? InferTypeMapping(params Expression[] expressions)
2321
{
2422
for (var i = 0; i < expressions.Length; i++)
2523
{

src/EFCore.Cosmos/Query/Internal/Expressions/ArrayConstantExpression.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
// ReSharper disable once CheckNamespace
5-
6-
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
7-
85
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
96

107
/// <summary>
@@ -18,7 +15,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
1815
/// doing so can result in application failures when updating to a new Entity Framework Core release.
1916
/// </remarks>
2017
[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
21-
public class ArrayConstantExpression(Type elementClrType, IReadOnlyList<SqlExpression> items, CosmosTypeMapping? typeMapping = null)
18+
public class ArrayConstantExpression(Type elementClrType, IReadOnlyList<SqlExpression> items, CoreTypeMapping? typeMapping = null)
2219
: SqlExpression(typeof(IEnumerable<>).MakeGenericType(elementClrType), typeMapping)
2320
{
2421
/// <summary>

src/EFCore.Cosmos/Query/Internal/Expressions/ArrayExpression.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
// ReSharper disable once CheckNamespace
5-
6-
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
7-
85
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
96

107
/// <summary>
@@ -21,7 +18,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
2118
/// doing so can result in application failures when updating to a new Entity Framework Core release.
2219
/// </remarks>
2320
[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
24-
public class ArrayExpression(SelectExpression subquery, Type arrayClrType, CosmosTypeMapping? arrayTypeMapping = null)
21+
public class ArrayExpression(SelectExpression subquery, Type arrayClrType, CoreTypeMapping? arrayTypeMapping = null)
2522
: SqlExpression(arrayClrType, arrayTypeMapping)
2623
{
2724
/// <summary>

src/EFCore.Cosmos/Query/Internal/Expressions/ExistsExpression.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
// ReSharper disable once CheckNamespace
5-
6-
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
7-
85
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
96

107
/// <summary>
@@ -31,7 +28,7 @@ public class ExistsExpression : SqlExpression
3128
/// any release. You should only use it directly in your code with extreme caution and knowing that
3229
/// doing so can result in application failures when updating to a new Entity Framework Core release.
3330
/// </summary>
34-
public ExistsExpression(SelectExpression subquery, CosmosTypeMapping? typeMapping)
31+
public ExistsExpression(SelectExpression subquery, CoreTypeMapping? typeMapping)
3532
: base(typeof(bool), typeMapping)
3633
{
3734
Subquery = subquery;

0 commit comments

Comments
 (0)