Skip to content

Commit d9e76b0

Browse files
committed
Get rid of excessive sorting of key columns on KeyExpression creation. Also some potential reallocations eliminated
1 parent 4bb2ba0 commit d9e76b0

2 files changed

Lines changed: 61 additions & 54 deletions

File tree

Orm/Xtensive.Orm/Orm/Linq/Expressions/FieldExpression.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,36 @@ internal class FieldExpression : PersistentFieldExpression
1818
{
1919
private IPersistentExpression owner;
2020

21-
public new FieldInfo Field { get; private set; }
21+
public new FieldInfo Field { get; }
2222

2323
public virtual IPersistentExpression Owner
2424
{
25-
get { return owner; }
25+
get => owner;
2626
internal set
2727
{
28-
if (owner!=null)
28+
if (owner!=null) {
2929
throw Exceptions.AlreadyInitialized("Owner");
30+
}
31+
3032
owner = value;
3133
}
3234
}
3335

3436
public override Expression Remap(int offset, Dictionary<Expression, Expression> processedExpressions)
3537
{
36-
if (!CanRemap)
38+
if (!CanRemap) {
3739
return this;
40+
}
3841

39-
Expression result;
40-
if (processedExpressions.TryGetValue(this, out result))
42+
if (processedExpressions.TryGetValue(this, out var result)) {
4143
return result;
44+
}
4245

4346
var mapping = new Segment<int>(Mapping.Offset + offset, Mapping.Length);
4447
result = new FieldExpression(ExtendedExpressionType.Field, Field, mapping, OuterParameter, DefaultIfEmpty);
45-
if (owner == null)
48+
if (owner == null) {
4649
return result;
50+
}
4751

4852
processedExpressions.Add(this, result);
4953
Owner.Remap(offset, processedExpressions);

Orm/Xtensive.Orm/Orm/Linq/Expressions/KeyExpression.cs

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
// Created by: Alexis Kochetov
55
// Created: 2009.05.05
66

7-
using System;
87
using System.Collections.Generic;
98
using System.Linq;
109
using System.Linq.Expressions;
1110
using System.Reflection;
12-
using Xtensive.Collections;
1311
using Xtensive.Core;
1412
using Xtensive.Orm.Model;
1513
using TypeInfo = Xtensive.Orm.Model.TypeInfo;
@@ -18,23 +16,24 @@ namespace Xtensive.Orm.Linq.Expressions
1816
{
1917
internal class KeyExpression : PersistentFieldExpression
2018
{
21-
public TypeInfo EntityType { get; private set; }
22-
public System.Collections.ObjectModel.ReadOnlyCollection<FieldExpression> KeyFields { get; private set; }
19+
public TypeInfo EntityType { get; }
20+
public IReadOnlyList<FieldExpression> KeyFields { get; }
2321

2422
public override Expression Remap(int offset, Dictionary<Expression, Expression> processedExpressions)
2523
{
26-
if (!CanRemap)
24+
if (!CanRemap) {
2725
return this;
26+
}
2827

29-
Expression value;
30-
if (processedExpressions.TryGetValue(this, out value))
28+
if (processedExpressions.TryGetValue(this, out var value)) {
3129
return value;
30+
}
3231

3332
var mapping = new Segment<int>(Mapping.Offset + offset, Mapping.Length);
34-
var fields = KeyFields
35-
.Select(f => (FieldExpression)f.Remap(offset, processedExpressions))
36-
.ToList()
37-
.AsReadOnly();
33+
34+
FieldExpression Remap(FieldExpression f) => (FieldExpression) f.Remap(offset, processedExpressions);
35+
36+
var fields = KeyFields.Select(Remap).ToArray(KeyFields.Count);
3837
var result = new KeyExpression(EntityType, fields, mapping, UnderlyingProperty, OuterParameter, DefaultIfEmpty);
3938

4039
processedExpressions.Add(this, result);
@@ -43,29 +42,29 @@ public override Expression Remap(int offset, Dictionary<Expression, Expression>
4342

4443
public override Expression Remap(int[] map, Dictionary<Expression, Expression> processedExpressions)
4544
{
46-
if (!CanRemap)
45+
if (!CanRemap) {
4746
return this;
47+
}
4848

49-
Expression value;
50-
if (processedExpressions.TryGetValue(this, out value))
49+
if (processedExpressions.TryGetValue(this, out var value)) {
5150
return value;
51+
}
5252

5353
var segment = new Segment<int>(map.IndexOf(Mapping.Offset), Mapping.Length);
54-
System.Collections.ObjectModel.ReadOnlyCollection<FieldExpression> fields;
54+
var fields = new FieldExpression[KeyFields.Count];
5555
using (new SkipOwnerCheckScope()) {
56-
fields = KeyFields
57-
.Select(f => f.Remap(map, processedExpressions))
58-
.Where(f => f != null)
59-
.Cast<FieldExpression>()
60-
.ToList()
61-
.AsReadOnly();
62-
}
63-
if (fields.Count != KeyFields.Count) {
64-
if (SkipOwnerCheckScope.IsActive) {
65-
processedExpressions.Add(this, null);
66-
return null;
56+
for (var index = 0; index < fields.Length; index++) {
57+
var field = (FieldExpression)KeyFields[index].Remap(map, processedExpressions);
58+
if (field == null) {
59+
if (SkipOwnerCheckScope.IsActive) {
60+
processedExpressions.Add(this, null);
61+
return null;
62+
}
63+
throw Exceptions.InternalError(Strings.ExUnableToRemapKeyExpression, OrmLog.Instance);
64+
}
65+
66+
fields[index] = field;
6767
}
68-
throw Exceptions.InternalError(Strings.ExUnableToRemapKeyExpression, OrmLog.Instance);
6968
}
7069
var result = new KeyExpression(EntityType, fields, segment, UnderlyingProperty, OuterParameter, DefaultIfEmpty);
7170

@@ -75,14 +74,14 @@ public override Expression Remap(int[] map, Dictionary<Expression, Expression> p
7574

7675
public override Expression BindParameter(ParameterExpression parameter, Dictionary<Expression, Expression> processedExpressions)
7776
{
78-
Expression value;
79-
if (processedExpressions.TryGetValue(this, out value))
77+
if (processedExpressions.TryGetValue(this, out var value)) {
8078
return value;
79+
}
80+
81+
FieldExpression BindParameter(FieldExpression f)
82+
=> (FieldExpression) f.BindParameter(parameter, processedExpressions);
8183

82-
var fields = KeyFields
83-
.Select(f => (FieldExpression)f.BindParameter(parameter, processedExpressions))
84-
.ToList()
85-
.AsReadOnly();
84+
var fields = KeyFields.Select(BindParameter).ToArray(KeyFields.Count);
8685
var result = new KeyExpression(EntityType, fields, Mapping, UnderlyingProperty, parameter, DefaultIfEmpty);
8786

8887
processedExpressions.Add(this, result);
@@ -91,14 +90,14 @@ public override Expression BindParameter(ParameterExpression parameter, Dictiona
9190

9291
public override Expression RemoveOuterParameter(Dictionary<Expression, Expression> processedExpressions)
9392
{
94-
Expression value;
95-
if (processedExpressions.TryGetValue(this, out value))
93+
if (processedExpressions.TryGetValue(this, out var value)) {
9694
return value;
95+
}
9796

98-
var fields = KeyFields
99-
.Select(f => (FieldExpression)f.RemoveOuterParameter(processedExpressions))
100-
.ToList()
101-
.AsReadOnly();
97+
FieldExpression RemoveOuterParameter(FieldExpression f)
98+
=> (FieldExpression) f.RemoveOuterParameter(processedExpressions);
99+
100+
var fields = KeyFields.Select(RemoveOuterParameter).ToArray(KeyFields.Count);
102101
var result = new KeyExpression(EntityType, fields, Mapping, UnderlyingProperty, null, DefaultIfEmpty);
103102

104103
processedExpressions.Add(this, result);
@@ -108,21 +107,25 @@ public override Expression RemoveOuterParameter(Dictionary<Expression, Expressio
108107
public static KeyExpression Create(TypeInfo entityType, int offset)
109108
{
110109
var mapping = new Segment<int>(offset, entityType.Key.TupleDescriptor.Count);
111-
var fields = entityType.Columns
112-
.Where(c => c.IsPrimaryKey)
113-
.OrderBy(c => c.Field.MappingInfo.Offset)
114-
.Select(c => FieldExpression.CreateField(c.Field, offset))
115-
.ToList()
116-
.AsReadOnly();
117-
return new KeyExpression(entityType, fields, mapping,WellKnownMembers.IEntityKey, null, false);
110+
111+
FieldExpression CreateField(ColumnInfo c) => FieldExpression.CreateField(c.Field, offset);
112+
113+
var fields = entityType.IsLocked
114+
? entityType.Key.Columns.Select(CreateField).ToArray(entityType.Key.Columns.Count)
115+
: entityType.Columns
116+
.Where(c => c.IsPrimaryKey)
117+
.OrderBy(c => c.Field.MappingInfo.Offset)
118+
.Select(CreateField)
119+
.ToArray();
120+
return new KeyExpression(entityType, fields, mapping, WellKnownMembers.IEntityKey, null, false);
118121
}
119122

120123

121124
// Constructors
122125

123126
private KeyExpression(
124127
TypeInfo entityType,
125-
System.Collections.ObjectModel.ReadOnlyCollection<FieldExpression> keyFields,
128+
IReadOnlyList<FieldExpression> keyFields,
126129
Segment<int> segment,
127130
PropertyInfo underlyingProperty,
128131
ParameterExpression parameterExpression,

0 commit comments

Comments
 (0)