Skip to content

Commit f955b08

Browse files
committed
Use read-only interfaces for querying EF Core model
1 parent 06d6b18 commit f955b08

File tree

5 files changed

+27
-26
lines changed

5 files changed

+27
-26
lines changed

src/Examples/DapperExample/TranslationToSql/DataModel/FromEntitiesDataModelService.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ public void Initialize(DbContext dbContext)
3838
Initialize();
3939
}
4040

41-
private void ScanForeignKeys(IModel entityModel)
41+
private void ScanForeignKeys(IReadOnlyModel entityModel)
4242
{
4343
foreach (RelationshipAttribute relationship in ResourceGraph.GetResourceTypes().SelectMany(resourceType => resourceType.Relationships))
4444
{
45-
IEntityType? leftEntityType = entityModel.FindEntityType(relationship.LeftType.ClrType);
46-
INavigation? navigation = leftEntityType?.FindNavigation(relationship.Property.Name);
45+
IReadOnlyEntityType? leftEntityType = entityModel.FindEntityType(relationship.LeftType.ClrType);
46+
IReadOnlyNavigation? navigation = leftEntityType?.FindNavigation(relationship.Property.Name);
4747

4848
if (navigation != null)
4949
{
@@ -57,23 +57,23 @@ private void ScanForeignKeys(IModel entityModel)
5757
}
5858
}
5959

60-
private void ScanColumnNullability(IModel entityModel)
60+
private void ScanColumnNullability(IReadOnlyModel entityModel)
6161
{
6262
foreach (ResourceType resourceType in ResourceGraph.GetResourceTypes())
6363
{
6464
ScanColumnNullability(resourceType, entityModel);
6565
}
6666
}
6767

68-
private void ScanColumnNullability(ResourceType resourceType, IModel entityModel)
68+
private void ScanColumnNullability(ResourceType resourceType, IReadOnlyModel entityModel)
6969
{
70-
IEntityType? entityType = entityModel.FindEntityType(resourceType.ClrType);
70+
IReadOnlyEntityType? entityType = entityModel.FindEntityType(resourceType.ClrType);
7171

7272
if (entityType != null)
7373
{
7474
foreach (AttrAttribute attribute in resourceType.Attributes)
7575
{
76-
IProperty? property = entityType.FindProperty(attribute.Property.Name);
76+
IReadOnlyProperty? property = entityType.FindProperty(attribute.Property.Name);
7777

7878
if (property != null)
7979
{

src/Examples/NoEntityFrameworkExample/QueryLayerToLinqConverter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
namespace NoEntityFrameworkExample;
99

10-
internal sealed class QueryLayerToLinqConverter(IModel model, IQueryableBuilder queryableBuilder)
10+
internal sealed class QueryLayerToLinqConverter(IReadOnlyModel entityModel, IQueryableBuilder queryableBuilder)
1111
{
12-
private readonly IModel _model = model;
12+
private readonly IReadOnlyModel _entityModel = entityModel;
1313
private readonly IQueryableBuilder _queryableBuilder = queryableBuilder;
1414

1515
public IEnumerable<TResource> ApplyQueryLayer<TResource>(QueryLayer queryLayer, IEnumerable<TResource> resources)
@@ -21,7 +21,7 @@ public IEnumerable<TResource> ApplyQueryLayer<TResource>(QueryLayer queryLayer,
2121

2222
// Convert QueryLayer into LINQ expression.
2323
IQueryable source = ((IEnumerable)resources).AsQueryable();
24-
var context = QueryableBuilderContext.CreateRoot(source, typeof(Enumerable), _model, null);
24+
var context = QueryableBuilderContext.CreateRoot(source, typeof(Enumerable), _entityModel, null);
2525
Expression expression = _queryableBuilder.ApplyQuery(queryLayer, context);
2626

2727
// Insert null checks to prevent a NullReferenceException during execution of expressions such as:

src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryClauseBuilderContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public sealed class QueryClauseBuilderContext
2929
/// <summary>
3030
/// The Entity Framework Core entity model.
3131
/// </summary>
32-
public IModel EntityModel { get; }
32+
public IReadOnlyModel EntityModel { get; }
3333

3434
/// <summary>
3535
/// Used to produce unique names for lambda parameters.
@@ -51,7 +51,7 @@ public sealed class QueryClauseBuilderContext
5151
/// </summary>
5252
public object? State { get; }
5353

54-
public QueryClauseBuilderContext(Expression source, ResourceType resourceType, Type extensionType, IModel entityModel,
54+
public QueryClauseBuilderContext(Expression source, ResourceType resourceType, Type extensionType, IReadOnlyModel entityModel,
5555
LambdaScopeFactory lambdaScopeFactory, LambdaScope lambdaScope, IQueryableBuilder queryableBuilder, object? state)
5656
{
5757
ArgumentGuard.NotNull(source);

src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilderContext.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public sealed class QueryableBuilderContext
2929
/// <summary>
3030
/// The Entity Framework Core entity model.
3131
/// </summary>
32-
public IModel EntityModel { get; }
32+
public IReadOnlyModel EntityModel { get; }
3333

3434
/// <summary>
3535
/// Used to produce unique names for lambda parameters.
@@ -41,7 +41,7 @@ public sealed class QueryableBuilderContext
4141
/// </summary>
4242
public object? State { get; }
4343

44-
public QueryableBuilderContext(Expression source, Type elementType, Type extensionType, IModel entityModel, LambdaScopeFactory lambdaScopeFactory,
44+
public QueryableBuilderContext(Expression source, Type elementType, Type extensionType, IReadOnlyModel entityModel, LambdaScopeFactory lambdaScopeFactory,
4545
object? state)
4646
{
4747
ArgumentGuard.NotNull(source);
@@ -58,15 +58,15 @@ public QueryableBuilderContext(Expression source, Type elementType, Type extensi
5858
State = state;
5959
}
6060

61-
public static QueryableBuilderContext CreateRoot(IQueryable source, Type extensionType, IModel model, object? state)
61+
public static QueryableBuilderContext CreateRoot(IQueryable source, Type extensionType, IReadOnlyModel entityModel, object? state)
6262
{
6363
ArgumentGuard.NotNull(source);
6464
ArgumentGuard.NotNull(extensionType);
65-
ArgumentGuard.NotNull(model);
65+
ArgumentGuard.NotNull(entityModel);
6666

6767
var lambdaScopeFactory = new LambdaScopeFactory();
6868

69-
return new QueryableBuilderContext(source.Expression, source.ElementType, extensionType, model, lambdaScopeFactory, state);
69+
return new QueryableBuilderContext(source.Expression, source.ElementType, extensionType, entityModel, lambdaScopeFactory, state);
7070
}
7171

7272
public QueryClauseBuilderContext CreateClauseContext(IQueryableBuilder queryableBuilder, Expression source, ResourceType resourceType,

src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ public virtual Expression ApplySelect(FieldSelection selection, QueryClauseBuild
4040
private Expression CreateLambdaBodyInitializer(FieldSelection selection, ResourceType resourceType, LambdaScope lambdaScope,
4141
bool lambdaAccessorRequiresTestForNull, QueryClauseBuilderContext context)
4242
{
43-
IEntityType entityType = context.EntityModel.FindEntityType(resourceType.ClrType)!;
44-
IEntityType[] concreteEntityTypes = entityType.GetConcreteDerivedTypesInclusive().ToArray();
43+
IReadOnlyEntityType entityType = context.EntityModel.FindEntityType(resourceType.ClrType)!;
44+
IReadOnlyEntityType[] concreteEntityTypes = entityType.GetConcreteDerivedTypesInclusive().ToArray();
4545

4646
Expression bodyInitializer = concreteEntityTypes.Length > 1
4747
? CreateLambdaBodyInitializerForTypeHierarchy(selection, resourceType, concreteEntityTypes, lambdaScope, context)
@@ -56,12 +56,12 @@ private Expression CreateLambdaBodyInitializer(FieldSelection selection, Resourc
5656
}
5757

5858
private Expression CreateLambdaBodyInitializerForTypeHierarchy(FieldSelection selection, ResourceType baseResourceType,
59-
IEnumerable<IEntityType> concreteEntityTypes, LambdaScope lambdaScope, QueryClauseBuilderContext context)
59+
IEnumerable<IReadOnlyEntityType> concreteEntityTypes, LambdaScope lambdaScope, QueryClauseBuilderContext context)
6060
{
6161
IReadOnlySet<ResourceType> resourceTypes = selection.GetResourceTypes();
6262
Expression rootCondition = lambdaScope.Accessor;
6363

64-
foreach (IEntityType entityType in concreteEntityTypes)
64+
foreach (IReadOnlyEntityType entityType in concreteEntityTypes)
6565
{
6666
ResourceType? resourceType = resourceTypes.SingleOrDefault(type => type.ClrType == entityType.ClrType);
6767

@@ -115,7 +115,7 @@ private Expression CreateLambdaBodyInitializerForSingleType(FieldSelection selec
115115
}
116116

117117
private static ICollection<PropertySelector> ToPropertySelectors(FieldSelectors fieldSelectors, ResourceType resourceType, Type elementType,
118-
IModel entityModel)
118+
IReadOnlyModel entityModel)
119119
{
120120
var propertySelectors = new Dictionary<PropertyInfo, PropertySelector>();
121121

@@ -134,17 +134,18 @@ private static ICollection<PropertySelector> ToPropertySelectors(FieldSelectors
134134
return propertySelectors.Values;
135135
}
136136

137-
private static void IncludeAllScalarProperties(Type elementType, Dictionary<PropertyInfo, PropertySelector> propertySelectors, IModel entityModel)
137+
private static void IncludeAllScalarProperties(Type elementType, Dictionary<PropertyInfo, PropertySelector> propertySelectors, IReadOnlyModel entityModel)
138138
{
139-
IEntityType entityType = entityModel.GetEntityTypes().Single(type => type.ClrType == elementType);
139+
IReadOnlyEntityType entityType = entityModel.GetEntityTypes().Single(type => type.ClrType == elementType);
140140

141-
foreach (IProperty property in entityType.GetProperties().Where(property => !property.IsShadowProperty()))
141+
foreach (IReadOnlyProperty property in entityType.GetProperties().Where(property => !property.IsShadowProperty()))
142142
{
143143
var propertySelector = new PropertySelector(property.PropertyInfo!);
144144
IncludeWritableProperty(propertySelector, propertySelectors);
145145
}
146146

147-
foreach (INavigation navigation in entityType.GetNavigations().Where(navigation => navigation.ForeignKey.IsOwnership && !navigation.IsShadowProperty()))
147+
foreach (IReadOnlyNavigation navigation in entityType.GetNavigations()
148+
.Where(navigation => navigation.ForeignKey.IsOwnership && !navigation.IsShadowProperty()))
148149
{
149150
var propertySelector = new PropertySelector(navigation.PropertyInfo!);
150151
IncludeWritableProperty(propertySelector, propertySelectors);

0 commit comments

Comments
 (0)