Skip to content

Commit 63a2c1b

Browse files
authored
Make KeyField be a record struct (#339) (#343)
* Make `KeyField` readonly struct (#339) * Use `FrozenSet` * .NET compatible syntax * .NET compatible syntax * missed static * EnsureCapacity() * Fix ValidateHierarchy
1 parent f7b3d1a commit 63a2c1b

File tree

8 files changed

+39
-100
lines changed

8 files changed

+39
-100
lines changed

Orm/Xtensive.Orm/Orm/Building/Builders/AttributeProcessor.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,26 @@ public void Process(HierarchyDef hierarchyDef, FieldDef fieldDef, KeyAttribute a
5555
"attribute.Position");
5656

5757
var keyField = new KeyField(fieldDef.Name, attribute.Direction);
58+
var hierarchyDefKeyFields = hierarchyDef.KeyFields;
5859

59-
if (hierarchyDef.KeyFields.Count > attribute.Position) {
60-
var current = hierarchyDef.KeyFields[attribute.Position];
61-
if (current != null) {
60+
if (hierarchyDefKeyFields.Count > attribute.Position) {
61+
var current = hierarchyDefKeyFields[attribute.Position];
62+
if (current != default) {
6263
throw new DomainBuilderException(string.Format(Strings.ExKeyFieldsXAndXHaveTheSamePositionX, current.Name,
6364
fieldDef.Name, attribute.Position));
6465
}
6566

66-
hierarchyDef.KeyFields[attribute.Position] = keyField;
67+
hierarchyDefKeyFields[attribute.Position] = keyField;
6768
}
6869
else {
69-
// Adding null stubs for not yet processed key fields
70-
while (hierarchyDef.KeyFields.Count < attribute.Position) {
71-
hierarchyDef.KeyFields.Add(null);
70+
// Adding default stubs for not yet processed key fields
71+
hierarchyDefKeyFields.EnsureCapacity(attribute.Position + 1);
72+
while (hierarchyDefKeyFields.Count < attribute.Position) {
73+
hierarchyDefKeyFields.Add(default);
7274
}
7375

7476
// Finally adding target key field at the specified position
75-
hierarchyDef.KeyFields.Add(keyField);
77+
hierarchyDefKeyFields.Add(keyField);
7678
}
7779
}
7880

Orm/Xtensive.Orm/Orm/Building/Definitions/HierarchyDef.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public sealed class HierarchyDef : Node
2525
/// <summary>
2626
/// Gets the fields that are included in the key for this hierarchy.
2727
/// </summary>
28-
public List<KeyField> KeyFields { get; private set; }
28+
public List<KeyField> KeyFields { get; } = new(WellKnown.MaxKeyFieldNumber);
2929

3030
/// <summary>
3131
/// Gets the <see cref="InheritanceSchema"/> for this hierarchy.
@@ -58,9 +58,8 @@ public sealed class HierarchyDef : Node
5858
internal HierarchyDef(TypeDef root)
5959
{
6060
Root = root;
61-
KeyFields = new List<KeyField>(WellKnown.MaxKeyFieldNumber);
6261
IsClustered = true;
6362
KeyGeneratorKind = KeyGeneratorKind.Default;
6463
}
6564
}
66-
}
65+
}

Orm/Xtensive.Orm/Orm/Building/FixupActionProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public void Process(AddPrimaryIndexAction action)
180180

181181
var hierarchyDef = context.ModelDef.FindHierarchy(hierarchyRoot);
182182

183-
foreach (KeyField pair in hierarchyDef.KeyFields)
183+
foreach (var pair in hierarchyDef.KeyFields)
184184
generatedIndex.KeyFields.Add(pair.Name, pair.Direction);
185185

186186
// Check if user added secondary index equal to auto-generated primary index

Orm/Xtensive.Orm/Orm/Building/ModelInspector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public static void Inspect(BuildingContext context, HierarchyDef hierarchyDef)
200200
}
201201

202202
// Should TypeId field be added to key fields?
203-
if (hierarchyDef.IncludeTypeId && hierarchyDef.KeyFields.Find(f => f.Name == WellKnown.TypeIdFieldName) == null) {
203+
if (hierarchyDef.IncludeTypeId && hierarchyDef.KeyFields.All(f => f.Name != WellKnown.TypeIdFieldName)) {
204204
context.ModelInspectionResult.Register(new AddTypeIdToKeyFieldsAction(hierarchyDef));
205205
}
206206

Orm/Xtensive.Orm/Orm/Building/Validator.cs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
// Created by: Dmitri Maximov
55
// Created: 2007.09.12
66

7-
using System;
8-
using System.Collections.Generic;
7+
using System.Collections.Frozen;
98
using System.Text.RegularExpressions;
109
using Xtensive.Orm.Building.Definitions;
1110
using Xtensive.Orm.Internals;
@@ -14,12 +13,13 @@
1413

1514
namespace Xtensive.Orm.Building
1615
{
17-
internal class Validator
16+
internal class Validator(IEnumerable<Type> validFieldTypes)
1817
{
19-
private readonly HashSet<Type> validFieldTypes;
20-
private readonly Regex columnNamingRule;
21-
private readonly Regex typeNamingRule;
22-
private readonly Regex fieldNamingRule;
18+
private static readonly Regex ColumnNamingRule = new(@"^[\w][\w\-\.]*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
19+
private static readonly Regex TypeNamingRule = new(@"^[\w][\w\-\.\(\),]*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
20+
private static readonly Regex FieldNamingRule = new(@"^[\w][\w\-\.]*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
21+
22+
private readonly FrozenSet<Type> validFieldTypes = validFieldTypes.Append(WellKnownOrmTypes.Key).ToFrozenSet();
2323

2424
/// <summary>
2525
/// Determines whether the specified name is valid.
@@ -41,13 +41,13 @@ public void ValidateName(string name, ValidationRule rule)
4141
case ValidationRule.Type:
4242
case ValidationRule.Schema:
4343
case ValidationRule.Database:
44-
namingRule = typeNamingRule;
44+
namingRule = TypeNamingRule;
4545
break;
4646
case ValidationRule.Field:
47-
namingRule = fieldNamingRule;
47+
namingRule = FieldNamingRule;
4848
break;
4949
case ValidationRule.Column:
50-
namingRule = columnNamingRule;
50+
namingRule = ColumnNamingRule;
5151
break;
5252
default:
5353
throw new ArgumentOutOfRangeException();
@@ -95,7 +95,7 @@ public void ValidateHierarchy(HierarchyDef hierarchyDef)
9595
}
9696

9797
// if one of key fields is TypeId field and number of fields == 2 then it is OK
98-
if (keyFields.Count == 2 && keyFields.Find(f => f.Name == WellKnown.TypeIdFieldName) != null) {
98+
if (keyFields.Count == 2 && keyFields.Any(f => f.Name == WellKnown.TypeIdFieldName)) {
9999
throw new DomainBuilderException(Strings.ExDefaultGeneratorCanServeHierarchyWithExactlyOneKeyField);
100100
}
101101
}
@@ -257,17 +257,6 @@ internal void EnsureIsNullable(Type valueType)
257257
}
258258
}
259259

260-
// Type initializer
261-
262-
public Validator(IEnumerable<Type> validFieldTypes)
263-
{
264-
columnNamingRule = new Regex(@"^[\w][\w\-\.]*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
265-
typeNamingRule = new Regex(@"^[\w][\w\-\.\(\),]*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
266-
fieldNamingRule = new Regex(@"^[\w][\w\-\.]*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
267-
268-
this.validFieldTypes = new HashSet<Type>(validFieldTypes) {WellKnownOrmTypes.Key};
269-
}
270-
271260
public void ValidateHierarchyEquality(TypeDef @interface, HierarchyDef first, HierarchyDef second)
272261
{
273262
// TypeId mode must match
@@ -277,17 +266,20 @@ public void ValidateHierarchyEquality(TypeDef @interface, HierarchyDef first, Hi
277266
@interface.Name, first.Root.Name, second.Root.Name));
278267
}
279268

269+
var firstKeyFields = first.KeyFields;
270+
var secondKeyFields = second.KeyFields;
271+
280272
// Number of key fields must match
281-
if (first.KeyFields.Count != second.KeyFields.Count) {
273+
if (firstKeyFields.Count != secondKeyFields.Count) {
282274
throw new DomainBuilderException(string.Format(
283275
Strings.ExImplementorsOfXInterfaceBelongToHierarchiesWithDifferentKeyStructureYZ,
284276
@interface.Name, first.Root.Name, second.Root.Name));
285277
}
286278

287279
// Type of each key field must match
288-
for (var i = 0; i < first.KeyFields.Count; i++) {
289-
var masterField = first.Root.Fields[first.KeyFields[i].Name];
290-
var candidateField = second.Root.Fields[second.KeyFields[i].Name];
280+
for (var i = 0; i < firstKeyFields.Count; i++) {
281+
var masterField = first.Root.Fields[firstKeyFields[i].Name];
282+
var candidateField = second.Root.Fields[secondKeyFields[i].Name];
291283
if (masterField.ValueType != candidateField.ValueType) {
292284
throw new DomainBuilderException(string.Format(
293285
Strings.ExImplementorsOfXInterfaceBelongToHierarchiesWithDifferentKeyStructureYZ,

Orm/Xtensive.Orm/Orm/Model/KeyField.cs

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,12 @@
44
// Created by: Dmitri Maximov
55
// Created: 2007.12.28
66

7-
using System;
87
using Xtensive.Core;
98

9+
namespace Xtensive.Orm.Model;
1010

11-
namespace Xtensive.Orm.Model
12-
{
13-
/// <summary>
14-
/// Describes a field that is a part of a primary key.
15-
/// </summary>
16-
[Serializable]
17-
public sealed class KeyField : Node
18-
{
19-
/// <summary>
20-
/// Gets or sets the direction.
21-
/// </summary>
22-
public Direction Direction { get; private set; }
23-
24-
/// <inheritdoc/>
25-
public override int GetHashCode() => HashCode.Combine(Name, Direction);
26-
27-
/// <inheritdoc/>
28-
public override bool Equals(object obj) =>
29-
ReferenceEquals(this, obj)
30-
|| obj is KeyField kf && Name == kf.Name && Direction == kf.Direction;
31-
32-
33-
// Constructors
34-
35-
/// <summary>
36-
/// Initializes a new instance of this class.
37-
/// </summary>
38-
/// <param name="name">The name.</param>
39-
public KeyField(string name)
40-
: this(name, Direction.Positive)
41-
{
42-
}
43-
44-
/// <summary>
45-
/// Initializes a new instance of the <see cref="KeyField"/> class.
46-
/// </summary>
47-
/// <param name="name">The name.</param>
48-
/// <param name="direction">The direction.</param>
49-
public KeyField(string name, Direction direction) : base(name)
50-
{
51-
Direction = direction;
52-
}
53-
}
54-
}
11+
/// <summary>
12+
/// Describes a field that is a part of a primary key.
13+
/// </summary>
14+
[Serializable]
15+
public record struct KeyField(string Name, Direction Direction = Direction.Positive);

Orm/Xtensive.Orm/Orm/Model/ModelVisitor.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ protected virtual TResult Visit(Node node) =>
2727
DomainModel domainModel => VisitDomainModel(domainModel),
2828
KeyInfo keyProviderInfo => VisitKeyInfo(keyProviderInfo),
2929
SequenceInfo sequenceInfo => VisitSequenceInfo(sequenceInfo),
30-
KeyField keyField => VisitKeyField(keyField),
3130
AssociationInfo association => VisitAssociationInfo(association),
3231
FieldInfo field => VisitFieldInfo(field),
3332
TypeInfo type => VisitTypeInfo(type),
@@ -38,13 +37,6 @@ protected virtual TResult Visit(Node node) =>
3837
_ => throw new ArgumentException(Strings.ExNodeTypeIsUnknown, "node")
3938
};
4039

41-
/// <summary>
42-
/// Visits key field.
43-
/// </summary>
44-
/// <param name="keyField">The key field.</param>
45-
/// <returns>Visit result.</returns>
46-
protected abstract TResult VisitKeyField(KeyField keyField);
47-
4840
/// <summary>
4941
/// Visits a column.
5042
/// </summary>
@@ -114,4 +106,4 @@ protected virtual TResult Visit(Node node) =>
114106
/// <param name="fullTextIndex">Full index of the text.</param>
115107
protected abstract TResult VisitFullTextIndexInfo(FullTextIndexInfo fullTextIndex);
116108
}
117-
}
109+
}

Orm/Xtensive.Orm/Orm/Upgrade/Internals/DomainModelConverter.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,6 @@ private IEnumerable<TableInfo> CreateTables(IndexInfo index)
337337

338338
#region Not supported
339339

340-
/// <inheritdoc/>
341-
/// <exception cref="NotSupportedException">Method is not supported.</exception>
342-
protected override IPathNode VisitKeyField(KeyField keyField)
343-
{
344-
throw new NotSupportedException(String.Format(Strings.ExVisitKeyFieldIsNotSupportedByX, typeof (DomainModelConverter)));
345-
}
346-
347340
/// <inheritdoc/>
348341
/// <exception cref="NotSupportedException">Method is not supported.</exception>
349342
protected override IPathNode VisitFieldInfo(FieldInfo field)

0 commit comments

Comments
 (0)