Skip to content

Commit 146c357

Browse files
authored
Merge pull request #293 from DataObjects-NET/master-domain-build-imp
Contains changes of PR #242 made ready to merge plus additional small improvements
2 parents 82d4613 + 167b790 commit 146c357

File tree

65 files changed

+845
-721
lines changed

Some content is hidden

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

65 files changed

+845
-721
lines changed

ChangeLog/7.1.0-Beta-2-dev.txt

+31
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,35 @@
1010
[main] Changed translation of queries when DomainConfiguration.ShareStorageSchemaOverNodes set to true
1111
[main] StorageDriver.Compile(ISqlCompileUnit, NodeConfiguration) became obsolete
1212
[main] SqlNodeActualizer became obsolete
13+
[main] TypeInfoCollection.FindAncestor method became obsolete, use new TypeInfo.Ancestor property
14+
[main] TypeInfoCollection.FindDescendants methods became obsolete, use new TypeInfo.DirectDescendants/.AllDescendants properties
15+
[main] TypeInfoCollection.FindInterfaces methods became obsolete, use new TypeInfo.DirectInterfaces/.AllInterfaces properties
16+
[main] TypeInfoCollection.FindImplementors methods became obsolete, use new TypeInfo.DirectImplementors/.AllImplementors properties
17+
[main] TypeInfoCollection.FindRoot method became obsolete, use introduced TypeInfo.Root property
18+
[main] TypeInfo.GetImplementors(bool) became obsolete, use new TypeInfo.DirectImplementors/.AllImplementors properties
19+
[main] TypeInfo.GetInterfaces(bool) became obsolete, use new TypeInfo.DirectInterfaces/.AllInterfaces properties
20+
[main] TypeInfo.GetDescendants(bool) became obsolete, use new TypeInfo.DirectDescendants/.AllDescendants properties
21+
[main] TypeInfo.GetAncestors() became obsolete, use new TypeInfo.Ancestors property
22+
[main] TypeInfo.GetRoot() became obsolete, use introduced TypeInfo.Root property
23+
[main] IPropertyValidator.IsImmediate is read-only now
24+
[main] PropertyValidator.IsImmediate property has no setter, only init
25+
[main] PropertyValidator.ValidateOnlyIfModified property has no setter, only init
26+
[main] PropertyValidator.SkipOnTransactionCommit property has no setter, only init
27+
[main] RecordSetHeader.OrderTupleDescriptor became nullable to compensate TupleDescriptor's transition to read-only struct
28+
[main] IndexInfo.FilterByTypes changed result type to IReadOnlyList<TypeInfo>
29+
[main] IndexInfo.SelectColumns changed result type to IReadOnlyList<int>
30+
[main] IndexInfo.ValueColumnsMap changed result type to IReadOnlyList<Pair<int, List<int>>>
1331
[main] SqlCompilerConfiguration's DatabaseMapping and SchemaMapping moved to SqlPostCompilerConfiguration
1432
[main] Some EventArgs inheritors that were sealed classes transformed to read-only structures
1533
[main] DbCommandEventArgs became read-only structure
34+
[main] ILockable.Lock() now has default implementation that refers to ILockable.Lock(true)
35+
[main] TupleDescriptor became read-only struct
36+
[main] InterfaceMapping became read-only struct
37+
[main] ColumnIndexMap became read-only struct and properties changed retun type to IReadOnlyList<int>
38+
[main] TopologicalSorter.Sort() methods return IEnumerable<T>, use .SortToList() if results are needed as collection
39+
[main] TypeHelper.OrderByInheritance() returns IEnumerable<T> to avoid copying
40+
[main] TypeHelper.GetInterfaces() became obsolete, GetInterfacesUnordered() and GetInterfacesOrderedByInheritance() introduced
41+
[main] TypeDef.Validators and FieldDef.Validators properties return List<T>
1642
[main] SqlCustomFunctionCall and SqlFunctionCall share one base type
1743
[main] SqlFunctionCall.Arguments property is IReadOnlyList now and parameters can't be changed after instance creation
1844
[main] Xtensive.Sql.Dml.Extensions.IsNullReference() extension method is marked obsolete, use 'is null' operator instead
@@ -24,8 +50,13 @@
2450
[main] Queries use parameters instead of constant values for type indentifiers within columns list
2551
[main] Added DomainConfiguration.PreferTypeIdsAsQueryParameters to choose between contants and parameters for TypeIds
2652
[main] ShareStorageSchemaOverNodes option now includes shared query cache when TypeIds as paremters are prefered
53+
[main] Introduced TypeInfo.Ancestor property
54+
[main] Introduced TypeInfo.DirectDescendants and.AllDescendants properties
55+
[main] Introduced TypeInfo.DirectInterfaces and.AllInterfaces properties
56+
[main] Introduced TypeInfo.DirectImplementors .AllImplementors properties
2757
[main] BitFaster.Caching package reference is updated to 1.0.7
2858
[main] No error caused by ambiguity due to new IQueryable extension methods of .Net 6
59+
[main] General performance and memory efficiency improvements
2960
[reprocessing] DomainBuildErrorEventArgs (not sealed) became read-only structure
3061
[reprocessing] ExecuteErrorEventArgs (not sealed) became read-only structure
3162
[tracking] TrackingCompletedEventArgs (sealed) became read-only structure

Orm/Xtensive.Orm.Tests.Core/Helpers/TopologicalSorterTest.cs

+6-10
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ private static void InternalPerformanceTest(int nodeCount, int averageConnection
6161
GC.GetTotalMemory(true);
6262
using (new Measurement("Sorting", nodeCount + connectionCount)) {
6363
List<Node<int, int>> removedEdges;
64-
var result = TopologicalSorter.Sort(nodes, out removedEdges);
64+
var result = TopologicalSorter.SortToList(nodes, out removedEdges);
6565
if (!allowLoops)
6666
Assert.AreEqual(nodeCount, result.Count);
6767
}
@@ -75,8 +75,7 @@ public void SelfReferenceTest()
7575
var connection = new NodeConnection<int, string>(node, node, "ConnectionItem");
7676
connection.BindToNodes();
7777

78-
List<NodeConnection<int, string>> removedEdges;
79-
List<int> result = TopologicalSorter.Sort(EnumerableUtils.One(node), out removedEdges);
78+
var result = TopologicalSorter.SortToList(EnumerableUtils.One(node), out var removedEdges);
8079
Assert.AreEqual(1, result.Count);
8180
Assert.AreEqual(node.Item, result[0]);
8281
Assert.AreEqual(1, removedEdges.Count);
@@ -97,8 +96,7 @@ public void RemoveWholeNodeTest()
9796

9897
// Remove edge by edge.
9998

100-
List<NodeConnection<int, string>> removedEdges;
101-
List<int> result = TopologicalSorter.Sort(new[] {node2, node1}, out removedEdges);
99+
var result = TopologicalSorter.SortToList(new[] {node2, node1}, out List<NodeConnection<int, string>> removedEdges);
102100
Assert.AreEqual(2, result.Count);
103101
Assert.AreEqual(node1.Item, result[0]);
104102
Assert.AreEqual(node2.Item, result[1]);
@@ -111,7 +109,7 @@ public void RemoveWholeNodeTest()
111109
connection12_2.BindToNodes();
112110
connection21_1.BindToNodes();
113111

114-
result = TopologicalSorter.Sort(new[] {node2, node1}, out removedEdges, true);
112+
result = TopologicalSorter.SortToList(new[] {node2, node1}, out removedEdges, true);
115113
Assert.AreEqual(2, result.Count);
116114
Assert.AreEqual(node1.Item, result[1]);
117115
Assert.AreEqual(node2.Item, result[0]);
@@ -131,8 +129,7 @@ public void CombinedTest()
131129

132130
private void TestSort<T>(T[] data, Predicate<T, T> connector, T[] expected, T[] loops)
133131
{
134-
List<Node<T, object>> actualLoopNodes;
135-
List<T> actual = TopologicalSorter.Sort(data, connector, out actualLoopNodes);
132+
var actual = TopologicalSorter.SortToList(data, connector, out List<Node<T, object>> actualLoopNodes);
136133
T[] actualLoops = null;
137134
if (actualLoopNodes != null)
138135
actualLoops = actualLoopNodes
@@ -143,8 +140,7 @@ private void TestSort<T>(T[] data, Predicate<T, T> connector, T[] expected, T[]
143140
AssertEx.HasSameElements(expected, actual);
144141
AssertEx.HasSameElements(loops, actualLoops);
145142

146-
List<NodeConnection<T, object>> removedEdges;
147-
List<T> sortWithRemove = TopologicalSorter.Sort(data, connector, out removedEdges);
143+
var sortWithRemove = TopologicalSorter.SortToList(data, connector, out List<NodeConnection<T, object>> removedEdges);
148144
Assert.AreEqual(sortWithRemove.Count, data.Length);
149145
if (loops == null) {
150146
Assert.AreEqual(sortWithRemove.Count, actual.Count);

Orm/Xtensive.Orm.Tests.Core/Tuples/TupleDescriptorTest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public void CombinedTest()
117117
desc = TestDescriptor(desc, new Type[] {typeof(bool?), typeof(bool), typeof(bool?)});
118118
}
119119

120-
private TupleDescriptor TestDescriptor(TupleDescriptor theSame, Type[] types)
120+
private TupleDescriptor TestDescriptor(TupleDescriptor? theSame, Type[] types)
121121
{
122122
var d1 = TupleDescriptor.Create(types);
123123
var d2 = TupleDescriptor.Create(types);

Orm/Xtensive.Orm.Tests.Framework/DomainModelExtensions.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public static void DumpAncestor(this TypeInfo target, int indent)
9292
public static void DumpDescendants(this TypeInfo target, int indent)
9393
{
9494
WriteLine(indent, "Descendants:");
95-
HashSet<TypeInfo> direct = new HashSet<TypeInfo>(target.DirectDescendants);
95+
var direct = target.DirectDescendants;
9696
foreach (TypeInfo descendant in target.AllDescendants) {
9797
if (direct.Contains(descendant))
9898
WriteLine(indent + 1, descendant.Name + " (direct)");
@@ -116,7 +116,7 @@ public static void DumpInterfaces(this TypeInfo target, int indent)
116116
public static void DumpImplementors(this TypeInfo target, int indent)
117117
{
118118
WriteLine(indent, "Implementors:");
119-
HashSet<TypeInfo> direct = new HashSet<TypeInfo>(target.DirectImplementors);
119+
var direct = target.DirectImplementors;
120120
foreach (TypeInfo implementor in target.AllImplementors) {
121121
if (direct.Contains(implementor))
122122
WriteLine(indent + 1, implementor.Name + " (direct)");

Orm/Xtensive.Orm/Core/Interfaces/ILockable.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public interface ILockable
2525
/// <summary>
2626
/// Locks the instance recursively.
2727
/// </summary>
28-
void Lock();
28+
void Lock() => Lock(true);
2929

3030
/// <summary>
3131
/// Locks the instance and (possibly) all dependent objects.

Orm/Xtensive.Orm/Core/LockableBase.cs

+2-10
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,13 @@ public void EnsureNotLocked()
4141

4242
// Constructors
4343

44-
/// <summary>
45-
/// Initializes new instance of this type.
46-
/// </summary>
47-
protected LockableBase()
48-
: this (false)
49-
{
50-
}
51-
5244
/// <summary>
5345
/// Initializes new instance of this type.
5446
/// </summary>
5547
/// <param name="isLocked">Initial <see cref="IsLocked"/> property value.</param>
56-
protected LockableBase(bool isLocked)
48+
protected LockableBase(bool isLocked = false)
5749
{
5850
IsLocked = isLocked;
5951
}
6052
}
61-
}
53+
}

Orm/Xtensive.Orm/InternalLogs.cs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using Xtensive.Orm.Logging;
34
using JetBrains.Annotations;
45

@@ -569,10 +570,8 @@ public static Exception Info(Exception exception)
569570
return exception;
570571
}
571572

572-
public static void Warning(string format, params object[] args)
573-
{
573+
public static void Warning(string format, params object[] args) =>
574574
instance.Warning(format, args);
575-
}
576575

577576
public static Exception Warning(Exception exception, string format, params object[] args)
578577
{
@@ -623,6 +622,4 @@ static TestLog()
623622
instance = manager.GetLog(Name);
624623
}
625624
}
626-
627625
}
628-

Orm/Xtensive.Orm/Modelling/NodeCollection.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,12 @@ internal void Add(Node node)
224224
if (node.Index!=list.Count)
225225
throw Exceptions.InternalError("Wrong NodeCollection.Add arguments: node.Index!=list.Count!", CoreLog.Instance);
226226
string name = node.Name;
227-
if (nameIndex.ContainsKey(name))
228-
throw Exceptions.InternalError("Wrong NodeCollection.Add arguments: nameIndex[node.Name]!=null!", CoreLog.Instance);
229227
int count = list.Count;
228+
if (!nameIndex.TryAdd(name, node)) {
229+
throw Exceptions.InternalError("Wrong NodeCollection.Add arguments: nameIndex[node.Name]!=null!", CoreLog.Instance);
230+
}
230231
try {
231232
list.Add(node);
232-
nameIndex.Add(name, node);
233233
OnCollectionChanged(new NotifyCollectionChangedEventArgs(
234234
NotifyCollectionChangedAction.Add, node.Index));
235235
}

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.ClassTable.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ private void BuildClassTableIndexes(TypeInfo type)
3131
// Skip indef building for inherited fields
3232
var hasInheritedFields = indexDescriptor.KeyFields
3333
.Select(kvp => type.Fields[kvp.Key])
34-
.Any(f => f.IsInherited);
34+
.Any(static f => f.IsInherited);
3535
if (hasInheritedFields) {
3636
continue;
3737
}
@@ -102,8 +102,8 @@ private void BuildClassTableIndexes(TypeInfo type)
102102
// Build virtual primary index
103103
if (ancestors.Count > 0) {
104104
var baseIndexes = new Stack<IndexInfo>();
105-
foreach (var ancestor in ancestors.Where(t => t.Fields.Any(f => !f.IsPrimaryKey && !f.IsTypeId && f.IsDeclared))) {
106-
var ancestorIndex = ancestor.Indexes.Single(i => i.IsPrimary && !i.IsVirtual);
105+
foreach (var ancestor in ancestors.Where(t => t.Fields.Any(static f => !f.IsPrimaryKey && !f.IsTypeId && f.IsDeclared))) {
106+
var ancestorIndex = ancestor.Indexes.Single(static i => i.IsPrimary && !i.IsVirtual);
107107
if (untypedIndexes.Contains(ancestorIndex) && ancestorIndex.ReflectedType == root) {
108108
ancestorIndex = ancestor.Indexes.Single(i => i.DeclaringIndex == ancestorIndex.DeclaringIndex && i.IsTyped);
109109
}
@@ -112,7 +112,7 @@ private void BuildClassTableIndexes(TypeInfo type)
112112
}
113113
}
114114
if (baseIndexes.Count > 0) {
115-
if (primaryIndex.ValueColumns.Count > 0 && type.Fields.Any(f => !f.IsPrimaryKey && !f.IsTypeId && f.IsDeclared)) {
115+
if (primaryIndex.ValueColumns.Count > 0 && type.Fields.Any(static f => !f.IsPrimaryKey && !f.IsTypeId && f.IsDeclared)) {
116116
baseIndexes.Push(primaryIndex);
117117
}
118118
else {

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.ClusteredIndexes.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ private void ChooseClusteredIndexes()
2323
var clusteredIndexesMap = new Dictionary<TypeInfo, IndexInfo>();
2424
queue.Enqueue(hierarchy.Root);
2525
while (queue.TryDequeue(out var type)) {
26-
foreach (var decendant in type.DirectDescendants)
26+
foreach (var decendant in type.DirectDescendants) {
2727
queue.Enqueue(decendant);
28+
}
2829
var clusteredIndexes = type.Indexes
2930
.Where(index => index.IsClustered && index.IsSecondary)
3031
.ToList();

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.ConcreteTable.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ private void BuildConcreteTableIndexes(TypeInfo type)
3030
// and if they have some indexes then IndexDef.IsInherited of them will be true and it's truth actually,
3131
// but fields inherited from removed entities will have FieldInfo.IsInherited = false.
3232
// So, if we check only IndexDef.IsInherited then some indexes will be ignored.
33-
if (indexDescriptor.IsInherited && indexDescriptor.KeyFields.Select(kf=> type.Fields[kf.Key]).Any(f=>f.IsInherited)) {
33+
if (indexDescriptor.IsInherited && indexDescriptor.KeyFields.Select(kf=> type.Fields[kf.Key]).Any(static f => f.IsInherited)) {
3434
continue;
3535
}
3636

@@ -92,8 +92,8 @@ private void BuildConcreteTableIndexes(TypeInfo type)
9292

9393
// Build primary virtual union index
9494
if (descendants.Count > 0) {
95-
var indexesToUnion = new List<IndexInfo>() { type.Indexes.PrimaryIndex };
96-
foreach (var index in descendants.Select(t => t.Indexes.PrimaryIndex)) {
95+
var indexesToUnion = new List<IndexInfo>(descendants.Count + 1) { type.Indexes.PrimaryIndex };
96+
foreach (var index in descendants.Select(static t => t.Indexes.PrimaryIndex)) {
9797
var indexView = BuildViewIndex(type, index);
9898
indexesToUnion.Add(indexView);
9999
}
@@ -128,7 +128,7 @@ private void BuildConcreteTableIndexes(TypeInfo type)
128128

129129
// Build virtual secondary indexes
130130
if (descendants.Count > 0) {
131-
foreach (var index in type.Indexes.Where(i => !i.IsPrimary && !i.IsVirtual).ToList()) {
131+
foreach (var index in type.Indexes.Where(static i => !i.IsPrimary && !i.IsVirtual).ToChainedBuffer()) {
132132
var isUntyped = untypedIndexes.Contains(index);
133133
var indexToUnion = isUntyped
134134
? type.Indexes.Single(i => i.DeclaringIndex == index.DeclaringIndex && i.IsTyped)

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.FullText.cs

+8-7
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@ private void BuildFullTextIndexesSingleTable(TypeInfo root, IEnumerable<FullText
6767
var types = new HashSet<TypeInfo>();
6868
foreach (var fullTextIndexDef in hierarchyIndexes) {
6969
var type = model.Types[fullTextIndexDef.Type.UnderlyingType];
70-
types.Add(type);
71-
foreach (var descendant in type.AllDescendants)
72-
types.Add(descendant);
70+
_ = types.Add(type);
71+
types.UnionWith(type.AllDescendants);
7372
foreach (var fullTextFieldDef in fullTextIndexDef.Fields) {
7473
var fullTextColumn = GetFullTextColumn(type, fullTextFieldDef);
7574
index.Columns.Add(fullTextColumn);
@@ -110,8 +109,8 @@ private static FullTextColumnInfo GetFullTextColumn(TypeInfo type, FullTextField
110109
typeColumn = field.Column;
111110
}
112111
return new FullTextColumnInfo(column) {
113-
IsAnalyzed = fullTextFieldDef.IsAnalyzed,
114-
Configuration = fullTextFieldDef.Configuration,
112+
IsAnalyzed = fullTextFieldDef.IsAnalyzed,
113+
Configuration = fullTextFieldDef.Configuration,
115114
TypeColumn = typeColumn
116115
};
117116
}
@@ -120,8 +119,9 @@ private Dictionary<TypeInfo, List<FullTextIndexDef>> GatherFullTextIndexDefinito
120119
{
121120
var model = context.Model;
122121
var processQueue = new Queue<TypeInfo>();
123-
foreach (var type in root.DirectDescendants)
122+
foreach (var type in root.DirectDescendants) {
124123
processQueue.Enqueue(type);
124+
}
125125

126126
var indexDefs = hierarchyIndexes.ToDictionary(
127127
ftid => model.Types[ftid.Type.UnderlyingType],
@@ -141,8 +141,9 @@ private Dictionary<TypeInfo, List<FullTextIndexDef>> GatherFullTextIndexDefinito
141141
}
142142
}
143143
if (typeHasIndexDef)
144-
foreach (var descendant in type.DirectDescendants)
144+
foreach (var descendant in type.DirectDescendants) {
145145
processQueue.Enqueue(descendant);
146+
}
146147
}
147148
return indexDefs;
148149
}

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.SingleTable.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private void BuildSingleTableIndexes(TypeInfo type)
3232
// and if they have some indexes then IndexDef.IsInherited of them will be true and it's truth actually,
3333
// but fields inherited from removed entities will have FieldInfo.IsInherited = false.
3434
// So, if we check only IndexDef.IsInherited then some indexes will be ignored.
35-
if (indexDescriptor.IsInherited && indexDescriptor.KeyFields.Select(kf => type.Fields[kf.Key]).Any(f => f.IsInherited)) {
35+
if (indexDescriptor.IsInherited && indexDescriptor.KeyFields.Select(kf => type.Fields[kf.Key]).Any(static f => f.IsInherited)) {
3636
continue;
3737
}
3838

@@ -83,10 +83,11 @@ private void BuildSingleTableIndexes(TypeInfo type)
8383
}
8484
var descendants = type.AllDescendants;
8585

86-
var primaryIndexFilterTypes = !type.IsAbstract
87-
? descendants.Prepend(type)
88-
: descendants;
89-
86+
var primaryIndexFilterTypes = new List<TypeInfo>(type.IsAbstract ? descendants.Count : descendants.Count + 1);
87+
if (!type.IsAbstract)
88+
primaryIndexFilterTypes.Add(type);
89+
primaryIndexFilterTypes.AddRange(descendants);
90+
9091
// Import inherited indexes
9192
var ancestorIndexes = root.Indexes
9293
.Where(i => types.Contains(i.ReflectedType) && !i.IsTyped)
@@ -106,7 +107,7 @@ private void BuildSingleTableIndexes(TypeInfo type)
106107
if (ancestorIndex.DeclaringType.IsInterface) {
107108
var filteredDescendants = descendants
108109
.Where(t => !t.IsAbstract && !t.DirectInterfaces.Contains(ancestorIndex.DeclaringType));
109-
var filterByTypes = new List<TypeInfo>();
110+
var filterByTypes = new List<TypeInfo>(2);
110111
if (!type.IsAbstract) {
111112
filterByTypes.Add(type);
112113
}

0 commit comments

Comments
 (0)