diff --git a/Directory.Build.props b/Directory.Build.props
index 5b17ca697b..f36acfd7a1 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -128,4 +128,7 @@
+
+ $(DefineConstants);DO_SAFE_COLLECTION_WRAPPER
+
diff --git a/Orm/Xtensive.Orm.Tests.Core/Helpers/TopologicalSorterTest.cs b/Orm/Xtensive.Orm.Tests.Core/Helpers/TopologicalSorterTest.cs
index cc257e8ef0..8f931b5f33 100644
--- a/Orm/Xtensive.Orm.Tests.Core/Helpers/TopologicalSorterTest.cs
+++ b/Orm/Xtensive.Orm.Tests.Core/Helpers/TopologicalSorterTest.cs
@@ -63,7 +63,7 @@ private static void InternalPerformanceTest(int nodeCount, int averageConnection
List> removedEdges;
var result = TopologicalSorter.SortToList(nodes, out removedEdges);
if (!allowLoops)
- Assert.AreEqual(nodeCount, result.Count);
+ Assert.AreEqual(nodeCount, result.Count());
}
GC.GetTotalMemory(true);
}
diff --git a/Orm/Xtensive.Orm/Core/Extensions/ListExtensions.cs b/Orm/Xtensive.Orm/Core/Extensions/ListExtensions.cs
index d50fdcb846..a26fc585b1 100644
--- a/Orm/Xtensive.Orm/Core/Extensions/ListExtensions.cs
+++ b/Orm/Xtensive.Orm/Core/Extensions/ListExtensions.cs
@@ -8,7 +8,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
-
+using System.Linq;
+using System.Runtime.CompilerServices;
namespace Xtensive.Core
{
@@ -119,5 +120,25 @@ public static void EnsureIndexIsValid(this IList list, int index)
if (index < 0 || index >= list.Count)
throw new IndexOutOfRangeException(Strings.ExIndexOutOfRange);
}
+
+#if DO_SAFE_COLLECTION_WRAPPER
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IReadOnlyList AsSafeWrapper(this List list) => list.AsReadOnly();
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IReadOnlyList AsSafeWrapper(this IReadOnlyList list) => Array.AsReadOnly(list.ToArray());
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IReadOnlyList AsSafeWrapper(this T[] array) => Array.AsReadOnly(array);
+#else
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IReadOnlyList AsSafeWrapper(this List list) => list;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IReadOnlyList AsSafeWrapper(this IReadOnlyList list) => list;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IReadOnlyList AsSafeWrapper(this T[] array) => array;
+#endif
}
-}
\ No newline at end of file
+}
diff --git a/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs b/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs
index 3ec6657269..10b3400c27 100644
--- a/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs
+++ b/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs
@@ -18,7 +18,7 @@ namespace Xtensive.Linq
///
public abstract class ExpressionVisitor : ExpressionVisitor
{
- protected override ReadOnlyCollection VisitExpressionList(ReadOnlyCollection expressions)
+ protected override IReadOnlyList VisitExpressionList(ReadOnlyCollection expressions)
{
bool isChanged = false;
var results = new List(expressions.Count);
@@ -28,7 +28,7 @@ protected override ReadOnlyCollection VisitExpressionList(ReadOnlyCo
results.Add(p);
isChanged |= !ReferenceEquals(expression, p);
}
- return isChanged ? results.AsReadOnly() : expressions;
+ return isChanged ? results.AsSafeWrapper() : expressions;
}
///
@@ -38,8 +38,8 @@ protected override ReadOnlyCollection VisitExpressionList(ReadOnlyCo
/// Visit result.
protected virtual ElementInit VisitElementInitializer(ElementInit initializer)
{
- ReadOnlyCollection arguments = VisitExpressionList(initializer.Arguments);
- if (arguments!=initializer.Arguments) {
+ var arguments = VisitExpressionList(initializer.Arguments);
+ if (arguments != initializer.Arguments) {
return Expression.ElementInit(initializer.AddMethod, arguments);
}
return initializer;
@@ -50,7 +50,7 @@ protected virtual ElementInit VisitElementInitializer(ElementInit initializer)
///
/// The original element initializer list.
/// Visit result.
- protected virtual ReadOnlyCollection VisitElementInitializerList(ReadOnlyCollection original)
+ protected virtual IReadOnlyList VisitElementInitializerList(ReadOnlyCollection original)
{
var results = new List();
bool isChanged = false;
@@ -60,7 +60,7 @@ protected virtual ReadOnlyCollection VisitElementInitializerList(Re
results.Add(p);
isChanged |= !ReferenceEquals(originalIntializer, p);
}
- return isChanged ? results.AsReadOnly() : original;
+ return isChanged ? results.AsSafeWrapper() : original;
}
///
@@ -253,7 +253,7 @@ protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBindi
///
/// The original binding list.
/// Visit result.
- protected virtual ReadOnlyCollection VisitBindingList(ReadOnlyCollection original)
+ protected virtual IReadOnlyList VisitBindingList(ReadOnlyCollection original)
{
var results = new List();
bool isChanged = false;
@@ -263,7 +263,7 @@ protected virtual ReadOnlyCollection VisitBindingList(ReadOnlyCol
results.Add(p);
isChanged |= !ReferenceEquals(originalBinding, p);
}
- return isChanged ? results.AsReadOnly() : original;
+ return isChanged ? results.AsSafeWrapper() : original;
}
protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
diff --git a/Orm/Xtensive.Orm/Linq/ExpressionVisitor{TResult}.cs b/Orm/Xtensive.Orm/Linq/ExpressionVisitor{TResult}.cs
index b9900b549c..c749422741 100644
--- a/Orm/Xtensive.Orm/Linq/ExpressionVisitor{TResult}.cs
+++ b/Orm/Xtensive.Orm/Linq/ExpressionVisitor{TResult}.cs
@@ -9,6 +9,7 @@
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using Xtensive.Reflection;
+using Xtensive.Core;
@@ -142,14 +143,14 @@ protected virtual TResult Visit(Expression e)
///
/// The expression list.
/// Visit result.
- protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection expressions)
+ protected virtual IReadOnlyList VisitExpressionList(ReadOnlyCollection expressions)
{
var results = new List(expressions.Count);
for (int i = 0, n = expressions.Count; i < n; i++) {
var p = Visit(expressions[i]);
results.Add(p);
}
- return results.AsReadOnly();
+ return results.AsSafeWrapper();
}
///
diff --git a/Orm/Xtensive.Orm/Orm/Building/Builders/AssociationBuilder.cs b/Orm/Xtensive.Orm/Orm/Building/Builders/AssociationBuilder.cs
index db882628e5..bb8e4da57d 100644
--- a/Orm/Xtensive.Orm/Orm/Building/Builders/AssociationBuilder.cs
+++ b/Orm/Xtensive.Orm/Orm/Building/Builders/AssociationBuilder.cs
@@ -80,7 +80,7 @@ public static void BuildReversedAssociation(BuildingContext context, Association
AssociationInfo existing;
if (!context.Model.Associations.TryGetValue(association.Name, out existing)) {
context.Model.Associations.Add(association);
- association.Ancestors.AddRange(field.Associations);
+ association.AddAncestors(field.Associations);
var associationsToRemove = field.Associations
.Where(a => a.TargetType == association.TargetType)
diff --git a/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs b/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs
index 3c6050ea40..571daa2606 100644
--- a/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs
+++ b/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs
@@ -239,7 +239,7 @@ private void PreprocessAssociations()
.ToList();
if (pairedAssociations.Count > 0) {
foreach (var paired in pairedAssociations) {
- paired.First.Ancestors.AddRange(interfaceAssociations);
+ paired.First.AddAncestors(interfaceAssociations);
if (paired.First.TargetType.IsInterface || typesWithProcessedInheritedAssociations.Contains(paired.First.TargetType))
AssociationBuilder.BuildReversedAssociation(context, paired.First, paired.Second);
else {
@@ -288,11 +288,13 @@ bool associationFilter(AssociationInfo a)
var interfaceAssociationsToRemove = interfaceAssociations
.Where(ia => ia.OwnerType != association.OwnerType)
.ToList();
- association.Ancestors.AddRange(interfaceAssociationsToRemove);
+ association.AddAncestors(interfaceAssociationsToRemove);
foreach (var interfaceAssociation in interfaceAssociationsToRemove)
interfaceAssociations.Remove(interfaceAssociation);
}
- refField.Associations.AddRange(interfaceAssociations);
+ if (interfaceAssociations.Count > 0) {
+ refField.Associations.AddRange(interfaceAssociations);
+ }
foreach (var association in inheritedAssociations) {
if (!refField.Associations.Contains(association.Name))
refField.Associations.Add(association);
diff --git a/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs b/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs
index 0db467dc80..eeb9c8719d 100644
--- a/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs
+++ b/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+
using Xtensive.Core;
using Xtensive.Orm.Building.Definitions;
using Xtensive.Orm.Building.DependencyGraph;
@@ -52,7 +53,7 @@ public TypeInfo BuildType(TypeDef typeDef)
MappingSchema = typeDef.MappingSchema,
HasVersionRoots = TypeHelper.GetInterfacesUnordered(typeDef.UnderlyingType)
.Any(static type => type == typeof(IHasVersionRoots)),
- Validators = validators.AsReadOnly(),
+ Validators = validators.AsSafeWrapper(),
};
if (typeDef.StaticTypeId != null) {
@@ -234,6 +235,16 @@ private FieldInfo BuildDeclaredField(TypeInfo type, FieldDef fieldDef)
{
BuildLog.Info(nameof(Strings.LogBuildingDeclaredFieldXY), type.Name, fieldDef.Name);
+ var validators = fieldDef.Validators;
+
+ if (fieldDef.IsStructure && DeclaresOnValidate(fieldDef.ValueType)) {
+ validators.Add(new StructureFieldValidator());
+ }
+
+ if (fieldDef.IsEntitySet && DeclaresOnValidate(fieldDef.ValueType)) {
+ validators.Add(new EntitySetFieldValidator());
+ }
+
var fieldInfo = new FieldInfo(type, fieldDef.Attributes) {
UnderlyingProperty = fieldDef.UnderlyingProperty,
Name = fieldDef.Name,
@@ -244,17 +255,9 @@ private FieldInfo BuildDeclaredField(TypeInfo type, FieldDef fieldDef)
Length = fieldDef.Length,
Scale = fieldDef.Scale,
Precision = fieldDef.Precision,
- Validators = fieldDef.Validators,
+ Validators = validators,
};
- if (fieldInfo.IsStructure && DeclaresOnValidate(fieldInfo.ValueType)) {
- fieldInfo.Validators.Add(new StructureFieldValidator());
- }
-
- if (fieldInfo.IsEntitySet && DeclaresOnValidate(fieldInfo.ValueType)) {
- fieldInfo.Validators.Add(new EntitySetFieldValidator());
- }
-
type.Fields.Add(fieldInfo);
if (fieldInfo.IsEntitySet) {
diff --git a/Orm/Xtensive.Orm/Orm/Building/BuildingContext.cs b/Orm/Xtensive.Orm/Orm/Building/BuildingContext.cs
index e911e81c5c..a4835f2fea 100644
--- a/Orm/Xtensive.Orm/Orm/Building/BuildingContext.cs
+++ b/Orm/Xtensive.Orm/Orm/Building/BuildingContext.cs
@@ -62,12 +62,12 @@ public sealed class BuildingContext
///
/// Gets all available implementations.
///
- public ICollection Modules { get; private set; }
+ public IReadOnlyList Modules { get; }
///
/// Gets all available implementations.
///
- public ICollection Modules2 { get; private set; }
+ public IReadOnlyList Modules2 { get; }
internal ModelDefBuilder ModelDefBuilder { get; set; }
diff --git a/Orm/Xtensive.Orm/Orm/Building/Definitions/FieldDef.cs b/Orm/Xtensive.Orm/Orm/Building/Definitions/FieldDef.cs
index 3fb5d381fd..b7814e0c2a 100644
--- a/Orm/Xtensive.Orm/Orm/Building/Definitions/FieldDef.cs
+++ b/Orm/Xtensive.Orm/Orm/Building/Definitions/FieldDef.cs
@@ -287,7 +287,7 @@ public string PairTo
///
/// Gets of instances associated with this field.
///
- public List Validators { get; private set; }
+ public List Validators { get; } = new();
internal bool IsDeclaredAsNullable
{
@@ -325,7 +325,6 @@ internal FieldDef(Type valueType, Validator validator)
if ((valueType.IsClass || valueType.IsInterface) && !IsStructure)
attributes |= FieldAttributes.Nullable;
ValueType = valueType;
- Validators = new List();
// Nullable
if (valueType.IsNullable()) {
diff --git a/Orm/Xtensive.Orm/Orm/Building/Definitions/TypeDef.cs b/Orm/Xtensive.Orm/Orm/Building/Definitions/TypeDef.cs
index 48c4c8fd18..071193139b 100644
--- a/Orm/Xtensive.Orm/Orm/Building/Definitions/TypeDef.cs
+++ b/Orm/Xtensive.Orm/Orm/Building/Definitions/TypeDef.cs
@@ -113,7 +113,7 @@ public NodeCollection Implementors
///
/// Gets instances associated with this type.
///
- public List Validators { get; private set; }
+ public List Validators { get; } = new();
///
/// Gets or sets the type discriminator value.
@@ -219,8 +219,6 @@ internal TypeDef(ModelDefBuilder builder, Type type, Validator validator)
implementors = IsInterface
? new NodeCollection(this, "Implementors")
: NodeCollection.Empty;
-
- Validators = new List();
}
}
}
\ No newline at end of file
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/IHasNestedNodes.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/IHasNestedNodes.cs
index 50d1354035..283995835e 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/IHasNestedNodes.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/IHasNestedNodes.cs
@@ -11,10 +11,10 @@ namespace Xtensive.Orm.Internals.Prefetch
{
internal interface IHasNestedNodes
{
- ReadOnlyCollection NestedNodes { get; }
+ IReadOnlyList NestedNodes { get; }
IReadOnlyCollection ExtractKeys(object target);
- IHasNestedNodes ReplaceNestedNodes(ReadOnlyCollection nestedNodes);
+ IHasNestedNodes ReplaceNestedNodes(IReadOnlyList nestedNodes);
}
}
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/KeyExtractorNode.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/KeyExtractorNode.cs
index 9b3af6a0e6..9eb36884c4 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/KeyExtractorNode.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/KeyExtractorNode.cs
@@ -15,7 +15,7 @@ internal class KeyExtractorNode : Node, IHasNestedNodes
{
public Func> KeyExtractor { get; }
- public ReadOnlyCollection NestedNodes { get; }
+ public IReadOnlyList NestedNodes { get; }
IReadOnlyCollection IHasNestedNodes.ExtractKeys(object target)
{
@@ -27,10 +27,8 @@ public IReadOnlyCollection ExtractKeys(T target)
return KeyExtractor.Invoke(target);
}
- public IHasNestedNodes ReplaceNestedNodes(ReadOnlyCollection nestedNodes)
- {
- return new KeyExtractorNode(KeyExtractor, nestedNodes);
- }
+ public IHasNestedNodes ReplaceNestedNodes(IReadOnlyList nestedNodes) =>
+ new KeyExtractorNode(KeyExtractor, nestedNodes);
public override Node Accept(NodeVisitor visitor)
{
@@ -42,7 +40,7 @@ protected override string GetDescription()
return $"KeyExtraction<{typeof(T).Name}>";
}
- public KeyExtractorNode(Func> extractor, ReadOnlyCollection nestedNodes)
+ public KeyExtractorNode(Func> extractor, IReadOnlyList nestedNodes)
: base("*")
{
ArgumentValidator.EnsureArgumentNotNull(extractor, nameof(extractor));
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeAggregator.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeAggregator.cs
index d239cce2a7..f5a7c1efbd 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeAggregator.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeAggregator.cs
@@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
+using Xtensive.Core;
namespace Xtensive.Orm.Internals.Prefetch
{
@@ -26,7 +27,7 @@ public static IList> Aggregate(IEnumerable VisitNodeList(ReadOnlyCollection nodes)
+ public override IReadOnlyList VisitNodeList(IReadOnlyList nodes)
{
var result = new List();
foreach (var group in nodes.Where(n => n!=null).GroupBy(n => n.Path)) {
@@ -36,11 +37,11 @@ public override ReadOnlyCollection VisitNodeList(ReadOnlyCollecti
result.Add(node);
else {
var nodeToVisit = (BaseFieldNode) container.ReplaceNestedNodes(
- new ReadOnlyCollection(group.Cast().SelectMany(c => c.NestedNodes).ToList()));
+ group.Cast().SelectMany(c => c.NestedNodes).ToList().AsSafeWrapper());
result.Add((BaseFieldNode) Visit(nodeToVisit));
}
}
- return new ReadOnlyCollection(result);
+ return result.AsSafeWrapper();
}
// Constructor
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeBuilder.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeBuilder.cs
index ebc5ad3fad..d0321d4432 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeBuilder.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeBuilder.cs
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2020 Xtensive LLC.
+// Copyright (C) 2012-2020 Xtensive LLC.
// This code is distributed under MIT license terms.
// See the License.txt file in the project root for more information.
// Created by: Denis Krjuchkov
@@ -119,9 +119,9 @@ private IEnumerable VisitMemberAccess(MemberExpression access)
return EnumerableUtils.One(result);
}
- private static ObjectModel.ReadOnlyCollection WrapNodes(IEnumerable nodes)
+ private static IReadOnlyList WrapNodes(IEnumerable nodes)
{
- return nodes.ToList().AsReadOnly();
+ return nodes.ToList().AsSafeWrapper();
}
private IEnumerable VisitChildren(Expression expression)
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeVisitor.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeVisitor.cs
index ce371ec875..ec98bc9a94 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeVisitor.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/NodeVisitor.cs
@@ -4,7 +4,9 @@
// Created by: Alexis Kochetov
// Created: 2011.01.14
+using System.Collections.Generic;
using System.Collections.ObjectModel;
+using Xtensive.Core;
namespace Xtensive.Orm.Internals.Prefetch
{
@@ -17,7 +19,7 @@ public virtual Node Visit(Node node)
return node.Accept(this);
}
- public virtual ReadOnlyCollection VisitNodeList(ReadOnlyCollection nodes)
+ public virtual IReadOnlyList VisitNodeList(IReadOnlyList nodes)
{
BaseFieldNode[] list = null;
var index = 0;
@@ -35,9 +37,7 @@ public virtual ReadOnlyCollection VisitNodeList(ReadOnlyCollectio
}
index++;
}
- return list==null
- ? nodes
- : new ReadOnlyCollection(list);
+ return list?.AsSafeWrapper() ?? nodes;
}
public virtual Node VisitKeyExtractorNode(KeyExtractorNode keyExtractorNode)
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ReferenceNode.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ReferenceNode.cs
index 5bceb8dc84..13577e3796 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ReferenceNode.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ReferenceNode.cs
@@ -15,7 +15,7 @@ internal sealed class ReferenceNode : BaseFieldNode, IHasNestedNodes
{
public TypeInfo ReferenceType { get; private set; }
- public ReadOnlyCollection NestedNodes { get; private set; }
+ public IReadOnlyList NestedNodes { get; private set; }
public IReadOnlyCollection ExtractKeys(object target)
{
@@ -30,10 +30,8 @@ public IReadOnlyCollection ExtractKeys(object target)
: new[] {referenceKey};
}
- public IHasNestedNodes ReplaceNestedNodes(ReadOnlyCollection nestedNodes)
- {
- return new ReferenceNode(Path, Field, ReferenceType, NestedNodes);
- }
+ public IHasNestedNodes ReplaceNestedNodes(IReadOnlyList nestedNodes) =>
+ new ReferenceNode(Path, Field, ReferenceType, NestedNodes);
public override Node Accept(NodeVisitor visitor)
{
@@ -42,7 +40,7 @@ public override Node Accept(NodeVisitor visitor)
// Constructors
- public ReferenceNode(string path, FieldInfo field, TypeInfo referenceType, ReadOnlyCollection nestedNodes)
+ public ReferenceNode(string path, FieldInfo field, TypeInfo referenceType, IReadOnlyList nestedNodes)
: base(path, field)
{
ReferenceType = referenceType;
diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/SetNode.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/SetNode.cs
index 5650ef97a9..8d00ff0ac4 100644
--- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/SetNode.cs
+++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/SetNode.cs
@@ -14,7 +14,7 @@ namespace Xtensive.Orm.Internals.Prefetch
{
internal class SetNode : BaseFieldNode, IHasNestedNodes
{
- public ReadOnlyCollection NestedNodes { get; }
+ public IReadOnlyList NestedNodes { get; }
public TypeInfo ElementType { get; }
@@ -30,7 +30,7 @@ public IReadOnlyCollection ExtractKeys(object target)
return fetchedKeys.ToArray(fetchedKeys.Count);
}
- public IHasNestedNodes ReplaceNestedNodes(ReadOnlyCollection nestedNodes) =>
+ public IHasNestedNodes ReplaceNestedNodes(IReadOnlyList nestedNodes) =>
new SetNode(Path, Field, ElementType, NestedNodes);
public override Node Accept(NodeVisitor visitor) => visitor.VisitSetNode(this);
@@ -38,7 +38,7 @@ public IHasNestedNodes ReplaceNestedNodes(ReadOnlyCollection nest
// Constructors
- public SetNode(string path, FieldInfo field, TypeInfo elementType, ReadOnlyCollection nestedNodes)
+ public SetNode(string path, FieldInfo field, TypeInfo elementType, IReadOnlyList nestedNodes)
: base(path, field)
{
ElementType = elementType;
diff --git a/Orm/Xtensive.Orm/Orm/Linq/Translator.Materialization.cs b/Orm/Xtensive.Orm/Orm/Linq/Translator.Materialization.cs
index 0da819fec2..080980bc39 100644
--- a/Orm/Xtensive.Orm/Orm/Linq/Translator.Materialization.cs
+++ b/Orm/Xtensive.Orm/Orm/Linq/Translator.Materialization.cs
@@ -89,9 +89,8 @@ private static ProjectionExpression Optimize(ProjectionExpression origin)
if (usedColumns.Count == 0)
usedColumns.Add(0);
if (usedColumns.Count < origin.ItemProjector.DataSource.Header.Length) {
- var usedColumnsArray = usedColumns.ToArray();
- var resultProvider = new SelectProvider(originProvider, usedColumnsArray);
- var itemProjector = origin.ItemProjector.Remap(resultProvider, usedColumnsArray);
+ var resultProvider = new SelectProvider(originProvider, usedColumns);
+ var itemProjector = origin.ItemProjector.Remap(resultProvider, usedColumns);
var result = origin.Apply(itemProjector);
return result;
}
diff --git a/Orm/Xtensive.Orm/Orm/Model/AssociationInfo.cs b/Orm/Xtensive.Orm/Orm/Model/AssociationInfo.cs
index e30f4cc7e5..3d84508a72 100644
--- a/Orm/Xtensive.Orm/Orm/Model/AssociationInfo.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/AssociationInfo.cs
@@ -5,6 +5,7 @@
// Created: 2008.07.02
using System;
+using System.Collections.Generic;
using System.Linq;
using Xtensive.Core;
using Xtensive.Tuples.Transform;
@@ -62,10 +63,8 @@ public TypeInfo AuxiliaryType
/// Gets or sets ancestor association.
///
/// The ancestor.
- public NodeCollection Ancestors
- {
- get { return ancestors; }
- }
+ public NodeCollection Ancestors =>
+ ancestors ??= new NodeCollection(this, "Ancestors");
///
/// Gets the underlying index for this instance.
@@ -194,6 +193,24 @@ public Tuple ExtractForeignKey(TypeInfo type, Tuple tuple)
throw new InvalidOperationException(Strings.ExCanNotExtractForeignKey);
}
+
+ internal void AddAncestors(IReadOnlyList associations)
+ {
+ if (associations.Count > 0) {
+ Ancestors.AddRange(associations);
+ }
+ }
+
+ public override void Lock(bool recursive)
+ {
+ base.Lock(recursive);
+ if (!recursive)
+ return;
+ if (ancestors is null || ancestors.Count == 0)
+ ancestors = NodeCollection.Empty;
+ else
+ ancestors.Lock(false);
+ }
///
public override void UpdateState()
@@ -245,7 +262,6 @@ public AssociationInfo(FieldInfo ownerField, TypeInfo targetType, Multiplicity m
Multiplicity = multiplicity;
OnOwnerRemove = onOwnerRemove;
OnTargetRemove = onTargetRemove;
- ancestors = new NodeCollection(this, "Ancestors");
}
}
-}
\ No newline at end of file
+}
diff --git a/Orm/Xtensive.Orm/Orm/Model/ColumnIndexMap.cs b/Orm/Xtensive.Orm/Orm/Model/ColumnIndexMap.cs
index 9e49ed67c6..9d859e1db5 100644
--- a/Orm/Xtensive.Orm/Orm/Model/ColumnIndexMap.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/ColumnIndexMap.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using Xtensive.Core;
namespace Xtensive.Orm.Model
diff --git a/Orm/Xtensive.Orm/Orm/Model/FieldInfo.cs b/Orm/Xtensive.Orm/Orm/Model/FieldInfo.cs
index b15369e0e1..1f8701ccc4 100644
--- a/Orm/Xtensive.Orm/Orm/Model/FieldInfo.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/FieldInfo.cs
@@ -51,7 +51,6 @@ public sealed class FieldInfo : MappedNode,
private TypeInfo declaringType;
private FieldInfo parent;
private ColumnInfo column;
- private NodeCollection associations;
private Type itemType;
private string originalName;
internal SegmentTransform valueExtractor;
@@ -60,7 +59,6 @@ public sealed class FieldInfo : MappedNode,
private int fieldId;
private int? cachedHashCode;
- private IList validators;
private Segment mappingInfo;
#region IsXxx properties
@@ -545,24 +543,22 @@ public ColumnInfo Column
///
public AssociationInfo GetAssociation(TypeInfo targetType)
{
- if (associations.Count == 0)
- return null;
-
- if (associations.Count == 1)
- return associations[0];
+ switch (Associations.Count) {
+ case 0:
+ return null;
+ case 1:
+ return Associations[0];
+ }
var ordered = IsLocked
- ? associations
- : associations.Reorder();
+ ? Associations
+ : Associations.Reorder();
return ordered.FirstOrDefault(
a => a.TargetType.UnderlyingType.IsAssignableFrom(targetType.UnderlyingType));
}
- public NodeCollection Associations
- {
- get { return associations; }
- }
+ public NodeCollection Associations { get; private set; }
///
/// Gets or sets field's adapter index.
@@ -582,14 +578,7 @@ public int AdapterIndex
/// Gets instances
/// associated with this field.
///
- public IList Validators
- {
- get { return validators; }
- internal set {
- EnsureNotLocked();
- validators = value;
- }
- }
+ public IReadOnlyList Validators { get; init; }
///
/// Gets value indicating if this field
@@ -658,7 +647,7 @@ public override void UpdateState()
columns?.Clear(); // To prevent event handler leak
columns = null;
- HasImmediateValidators = validators.Count > 0 && validators.Any(v => v.IsImmediate);
+ HasImmediateValidators = Validators.Count > 0 && Validators.Any(v => v.IsImmediate);
CreateMappingInfo();
}
@@ -669,16 +658,14 @@ public override void Lock(bool recursive)
base.Lock(recursive);
if (!recursive)
return;
- validators = Array.AsReadOnly(validators.ToArray());
Fields.Lock(true);
- if (column != null)
- column.Lock(true);
- if (associations.Count > 1) {
- var sorted = associations.Reorder();
- associations = new NodeCollection(associations.Owner, associations.Name);
- associations.AddRange(sorted);
+ column?.Lock(true);
+ if (Associations.Count > 1) {
+ var sorted = Associations.Reorder();
+ Associations = new NodeCollection(Associations.Owner, Associations.Name);
+ Associations.AddRange(sorted);
}
- associations.Lock(false);
+ Associations?.Lock(false);
}
private void CreateMappingInfo()
@@ -778,9 +765,11 @@ public FieldInfo Clone()
defaultValue = defaultValue,
defaultSqlExpression = defaultSqlExpression,
DeclaringField = DeclaringField,
- Validators = Validators.Select(v => v.CreateNew()).ToList(),
+ Validators = Validators.Select(v => v.CreateNew()).ToArray(),
};
- clone.Associations.AddRange(associations);
+ if (Associations.Count > 0) {
+ clone.Associations.AddRange(Associations);
+ }
return clone;
}
@@ -805,10 +794,8 @@ private FieldInfo(TypeInfo declaringType, TypeInfo reflectedType, FieldAttribute
Attributes = attributes;
this.declaringType = declaringType;
this.reflectedType = reflectedType;
- Fields = IsEntity || IsStructure
- ? new FieldInfoCollection(this, "Fields")
- : FieldInfoCollection.Empty;
- associations = new NodeCollection(this, "Associations");
+ Fields = IsEntity || IsStructure ? new FieldInfoCollection(this, "Fields") : FieldInfoCollection.Empty;
+ Associations = IsEntity || IsEntitySet ? new NodeCollection(this, "Associations") : NodeCollection.Empty;
}
}
-}
\ No newline at end of file
+}
diff --git a/Orm/Xtensive.Orm/Orm/Model/HierarchyInfo.cs b/Orm/Xtensive.Orm/Orm/Model/HierarchyInfo.cs
index 7ced941373..cf8643f398 100644
--- a/Orm/Xtensive.Orm/Orm/Model/HierarchyInfo.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/HierarchyInfo.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using Xtensive.Core;
namespace Xtensive.Orm.Model
{
@@ -47,7 +48,7 @@ public override void UpdateState()
Key.UpdateState();
var list = new List(Root.AllDescendants.Count + 1) {Root};
list.AddRange(Root.AllDescendants);
- Types = list.AsReadOnly();
+ Types = list.AsSafeWrapper();
if (Types.Count == 1)
InheritanceSchema = InheritanceSchema.ConcreteTable;
if (TypeDiscriminatorMap != null)
@@ -67,16 +68,16 @@ public override void Lock(bool recursive)
// Constructors
///
- /// Initializes a new instance of this class.
+ /// Initializes a new instance of this class.
///
/// The hierarchy root.
/// The key info.
/// The inheritance schema.
/// The type discriminator map.
public HierarchyInfo(
- TypeInfo root,
- KeyInfo key,
- InheritanceSchema inheritanceSchema,
+ TypeInfo root,
+ KeyInfo key,
+ InheritanceSchema inheritanceSchema,
TypeDiscriminatorMap typeDiscriminatorMap)
{
Root = root;
diff --git a/Orm/Xtensive.Orm/Orm/Model/IndexInfo.cs b/Orm/Xtensive.Orm/Orm/Model/IndexInfo.cs
index 370095e3be..23c5633102 100644
--- a/Orm/Xtensive.Orm/Orm/Model/IndexInfo.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/IndexInfo.cs
@@ -35,7 +35,7 @@ public sealed class IndexInfo : MappedNode
private readonly IndexInfo declaringIndex;
private double fillFactor;
private string shortName;
- private ReadOnlyCollection columns;
+ private IReadOnlyList columns;
private TupleDescriptor tupleDescriptor;
private TupleDescriptor keyTupleDescriptor;
private IReadOnlyList filterByTypes;
@@ -339,7 +339,7 @@ public override void UpdateState()
var lazy = new List();
var regular = new List();
- for (int i = 0; i < columns.Count; i++) {
+ for (int i = 0, count = columns.Count; i < count; i++) {
var item = columns[i];
if (item.IsPrimaryKey || item.IsSystem)
system.Add(i);
@@ -393,7 +393,7 @@ private void CreateColumns()
var result = new List(keyColumns.Count + valueColumns.Count);
result.AddRange(keyColumns.Select(static pair => pair.Key));
result.AddRange(valueColumns);
- columns = result.AsReadOnly();
+ columns = result.AsSafeWrapper();
}
diff --git a/Orm/Xtensive.Orm/Orm/Model/PartialIndexFilterInfo.cs b/Orm/Xtensive.Orm/Orm/Model/PartialIndexFilterInfo.cs
index 8de3e95f09..b37d3f18d9 100644
--- a/Orm/Xtensive.Orm/Orm/Model/PartialIndexFilterInfo.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/PartialIndexFilterInfo.cs
@@ -32,12 +32,12 @@ public LambdaExpression Expression
}
}
- private IList fields;
+ private IReadOnlyList fields;
///
/// Fields used in .
///
- public IList Fields
+ public IReadOnlyList Fields
{
get { return fields; }
set
@@ -56,9 +56,6 @@ public override void Lock(bool recursive)
throw Exceptions.NotInitialized("Expression");
if (Fields==null)
throw Exceptions.NotInitialized("Fields");
- fields = fields is List list
- ? list.AsReadOnly()
- : (IList) fields.ToList().AsReadOnly();
base.Lock(recursive);
}
}
diff --git a/Orm/Xtensive.Orm/Orm/Model/TypeIndexInfoCollection.cs b/Orm/Xtensive.Orm/Orm/Model/TypeIndexInfoCollection.cs
index 2911d4b34c..8c51be8372 100644
--- a/Orm/Xtensive.Orm/Orm/Model/TypeIndexInfoCollection.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/TypeIndexInfoCollection.cs
@@ -8,6 +8,7 @@
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
+using Xtensive.Core;
namespace Xtensive.Orm.Model
{
@@ -39,7 +40,7 @@ public IReadOnlyList RealPrimaryIndexes
get {
return IsLocked
? realPrimaryIndexes
- : FindRealPrimaryIndexes(PrimaryIndex).AsReadOnly();
+ : FindRealPrimaryIndexes(PrimaryIndex).AsSafeWrapper();
}
}
@@ -76,8 +77,8 @@ public override void UpdateState()
{
base.UpdateState();
primaryIndex = FindPrimaryIndex();
- realPrimaryIndexes = FindRealPrimaryIndexes(primaryIndex).AsReadOnly();
- indexesContainingAllData = FindIndexesContainingAllData().AsReadOnly();
+ realPrimaryIndexes = FindRealPrimaryIndexes(primaryIndex).AsSafeWrapper();
+ indexesContainingAllData = FindIndexesContainingAllData().AsSafeWrapper();
}
private IndexInfo GetIndex(IEnumerable fields)
@@ -118,7 +119,7 @@ public IReadOnlyList GetIndexesContainingAllData()
{
return IsLocked
? indexesContainingAllData
- : FindIndexesContainingAllData().AsReadOnly();
+ : FindIndexesContainingAllData().AsSafeWrapper();
}
private List FindIndexesContainingAllData()
diff --git a/Orm/Xtensive.Orm/Orm/Model/TypeInfo.cs b/Orm/Xtensive.Orm/Orm/Model/TypeInfo.cs
index cb3521f44e..f2b41d653f 100644
--- a/Orm/Xtensive.Orm/Orm/Model/TypeInfo.cs
+++ b/Orm/Xtensive.Orm/Orm/Model/TypeInfo.cs
@@ -610,7 +610,7 @@ public IEnumerable GetTargetAssociations()
if (!IsLocked) {
return result;
}
- targetAssociations = result.ToList().AsReadOnly();
+ targetAssociations = result.ToList().AsSafeWrapper();
}
return targetAssociations;
}
@@ -625,7 +625,7 @@ public IEnumerable GetOwnerAssociations()
if (!IsLocked) {
return result;
}
- ownerAssociations = result.ToList().AsReadOnly();
+ ownerAssociations = result.ToList().AsSafeWrapper();
}
return ownerAssociations;
}
@@ -737,7 +737,7 @@ public override void UpdateState()
}
}
- HasValidators = Validators.Count > 0 || fields.Any(f => f.HasValidators);
+ HasValidators = Validators.Count > 0 || fields.Any(static f => f.HasValidators);
// Selecting master parts from paired associations & single associations
var associations = model.Associations.Find(this)
@@ -798,7 +798,7 @@ public override void UpdateState()
var sortedRemovalSequence = sequence.Where(a => a.Ancestors.Count > 0).ToList();
if (sortedRemovalSequence.Count == 0) {
- removalSequence = sequence.AsReadOnly();
+ removalSequence = sequence.AsSafeWrapper();
}
else {
var sequenceSize = sequence.Count;
@@ -806,7 +806,7 @@ public override void UpdateState()
sortedRemovalSequence.Capacity = sequenceSize;
}
sortedRemovalSequence.AddRange(sequence.Where(a => a.Ancestors.Count == 0));
- removalSequence = sortedRemovalSequence.AsReadOnly();
+ removalSequence = sortedRemovalSequence.AsSafeWrapper();
}
}
diff --git a/Orm/Xtensive.Orm/Orm/Providers/Persister.cs b/Orm/Xtensive.Orm/Orm/Providers/Persister.cs
index 6d6733d023..f36c539733 100644
--- a/Orm/Xtensive.Orm/Orm/Providers/Persister.cs
+++ b/Orm/Xtensive.Orm/Orm/Providers/Persister.cs
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Xtensive LLC.
+// Copyright (C) 2012 Xtensive LLC.
// All rights reserved.
// For conditions of distribution and use, see license.
// Created by: Denis Krjuchkov
@@ -93,11 +93,10 @@ private SqlPersistTask CreateRemoveTask(PersistAction action, bool validateVersi
}
}
- private ICollection GetOrBuildRequest(StorageNode node, PersistRequestBuilderTask task)
+ private IReadOnlyList GetOrBuildRequest(StorageNode node, PersistRequestBuilderTask task)
{
var cache = node.PersistRequestCache;
- ICollection result;
- if (cache.TryGetValue(task, out result))
+ if (cache.TryGetValue(task, out var result))
return result;
result = requestBuilder.Build(node, task);
return cache.TryAdd(task, result) ? result : cache[task];
diff --git a/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs b/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs
index 2ef5b920a5..36210481bf 100644
--- a/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs
+++ b/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using Xtensive.Core;
using Xtensive.Orm.Configuration;
using Xtensive.Orm.Model;
using Xtensive.Sql;
@@ -23,7 +24,7 @@ public class PersistRequestBuilder : DomainBoundHandler
private ProviderInfo providerInfo;
private StorageDriver driver;
- internal ICollection Build(StorageNode node, PersistRequestBuilderTask task)
+ internal IReadOnlyList Build(StorageNode node, PersistRequestBuilderTask task)
{
var context = new PersistRequestBuilderContext(task, node.Mapping, node.Configuration);
List result;
@@ -52,14 +53,14 @@ internal ICollection Build(StorageNode node, PersistRequestBuild
}
var batchRequest = CreatePersistRequest(batch, bindings, node.Configuration);
batchRequest.Prepare();
- return new List {batchRequest}.AsReadOnly();
+ return new List { batchRequest }.AsSafeWrapper();
}
foreach (var item in result) {
item.Prepare();
}
- return result.AsReadOnly();
+ return result.AsSafeWrapper();
}
protected virtual List BuildInsertRequest(PersistRequestBuilderContext context)
diff --git a/Orm/Xtensive.Orm/Orm/Rse/Providers/Compilable/SelectProvider.cs b/Orm/Xtensive.Orm/Orm/Rse/Providers/Compilable/SelectProvider.cs
index 181e0054d4..5cfd06f4d0 100644
--- a/Orm/Xtensive.Orm/Orm/Rse/Providers/Compilable/SelectProvider.cs
+++ b/Orm/Xtensive.Orm/Orm/Rse/Providers/Compilable/SelectProvider.cs
@@ -44,17 +44,7 @@ protected override string ParametersToString()
public SelectProvider(CompilableProvider provider, IReadOnlyList columnIndexes)
: base(ProviderType.Select, provider)
{
- switch (columnIndexes) {
- case int[] indexArray:
- ColumnIndexes = Array.AsReadOnly(indexArray);
- break;
- case List indexList:
- ColumnIndexes = indexList.AsReadOnly();
- break;
- default:
- ColumnIndexes = columnIndexes;
- break;
- }
+ ColumnIndexes = columnIndexes.AsSafeWrapper();
Initialize();
}
diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs
index 257716a6a2..d346556d93 100644
--- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs
+++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs
@@ -78,7 +78,7 @@ protected override Provider VisitSelect(SelectProvider provider)
mappings[provider] = newMappings;
return source == provider.Source
? provider
- : new SelectProvider(source, indexColumns.ToArray());
+ : new SelectProvider(source, indexColumns);
}
///
@@ -122,7 +122,7 @@ protected override Provider VisitJoin(JoinProvider provider)
{
// split
- SplitMappings(provider, out var leftMapping, out var rightMapping);
+ var (leftMapping, rightMapping) = SplitMappings(provider);
leftMapping = Merge(leftMapping, provider.EqualIndexes.Select(p => p.First));
rightMapping = Merge(rightMapping, provider.EqualIndexes.Select(p => p.Second));
@@ -148,7 +148,7 @@ protected override Provider VisitJoin(JoinProvider provider)
protected override Provider VisitPredicateJoin(PredicateJoinProvider provider)
{
- SplitMappings(provider, out var leftMapping, out var rightMapping);
+ var (leftMapping, rightMapping) = SplitMappings(provider);
leftMapping.AddRange(mappingsGatherer.Gather(provider.Predicate,
provider.Predicate.Parameters[0]));
@@ -190,7 +190,7 @@ protected override Provider VisitApply(ApplyProvider provider)
{
// split
- SplitMappings(provider, out var leftMapping, out var rightMapping);
+ var (leftMapping, rightMapping) = SplitMappings(provider);
var applyParameter = provider.ApplyParameter;
var currentOuterUsages = new List();
@@ -217,12 +217,12 @@ protected override Provider VisitApply(ApplyProvider provider)
_ = outerColumnUsages.Remove(applyParameter);
var pair = OverrideRightApplySource(provider, newRightProvider, rightMapping);
- if (pair.First == null) {
+ if (pair.compilableProvider == null) {
rightMapping = mappings[provider.Right];
}
else {
- newRightProvider = pair.First;
- rightMapping = pair.Second;
+ newRightProvider = pair.compilableProvider;
+ rightMapping = pair.mapping;
}
RestoreMappings(oldMappings);
@@ -400,9 +400,8 @@ private static CompilableProvider BuildSetOperationSource(CompilableProvider pro
return new SelectProvider(provider, columns);
}
- protected virtual Pair> OverrideRightApplySource(ApplyProvider applyProvider,
- CompilableProvider provider, List requestedMapping) =>
- new Pair>(provider, requestedMapping);
+ protected virtual (CompilableProvider compilableProvider, List mapping) OverrideRightApplySource(ApplyProvider applyProvider, CompilableProvider provider, List requestedMapping) =>
+ (provider, requestedMapping);
#endregion
@@ -441,20 +440,21 @@ private static List MergeMappings(Provider originalLeft, List leftMap,
return result;
}
- private void SplitMappings(BinaryProvider provider, out List leftMapping, out List rightMapping)
+ private (List leftMapping, List rightMapping) SplitMappings(BinaryProvider provider)
{
var binaryMapping = mappings[provider];
- leftMapping = new List(binaryMapping.Count);
+ var leftMapping = new List(binaryMapping.Count);
var leftCount = provider.Left.Header.Length;
var index = 0;
while (index < binaryMapping.Count && binaryMapping[index] < leftCount) {
leftMapping.Add(binaryMapping[index]);
index++;
}
- rightMapping = new List(binaryMapping.Count - index);
+ var rightMapping = new List(binaryMapping.Count - index);
for (var i = index; i < binaryMapping.Count; i++) {
rightMapping.Add(binaryMapping[i] - leftCount);
}
+ return (leftMapping, rightMapping);
}
private void RegisterOuterMapping(ApplyParameter parameter, int value)
@@ -508,7 +508,7 @@ private void VisitJoin(ref List leftMapping, ref CompilableProvider left, r
private Dictionary> ReplaceMappings(Provider firstNewKey, List firstNewValue)
{
var oldMappings = mappings;
- mappings = new Dictionary> {{firstNewKey, firstNewValue}};
+ mappings = new() { { firstNewKey, firstNewValue } };
return oldMappings;
}
diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/RedundantColumnRemover.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/RedundantColumnRemover.cs
index 9ef551e717..39fe411f27 100644
--- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/RedundantColumnRemover.cs
+++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/RedundantColumnRemover.cs
@@ -27,13 +27,13 @@ internal sealed class RedundantColumnRemover : ColumnMappingInspector
&& methodInfo.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == WellKnownTypes.FuncOfTArgTResultType)
.CachedMakeGenericMethod(WellKnownOrmTypes.Tuple, WellKnownOrmTypes.Tuple);
- protected override Pair> OverrideRightApplySource(ApplyProvider applyProvider, CompilableProvider provider, List requestedMapping)
+ protected override (CompilableProvider, List) OverrideRightApplySource(ApplyProvider applyProvider, CompilableProvider provider, List requestedMapping)
{
var currentMapping = mappings[applyProvider.Right];
if (currentMapping.SequenceEqual(requestedMapping))
return base.OverrideRightApplySource(applyProvider, provider, requestedMapping);
var selectProvider = new SelectProvider(provider, requestedMapping.ToArray());
- return new Pair>(selectProvider, requestedMapping);
+ return (selectProvider, requestedMapping);
}
protected override Provider VisitRaw(RawProvider provider)
diff --git a/Orm/Xtensive.Orm/Orm/StorageNode.cs b/Orm/Xtensive.Orm/Orm/StorageNode.cs
index 20ac4d09b1..8c339a341e 100644
--- a/Orm/Xtensive.Orm/Orm/StorageNode.cs
+++ b/Orm/Xtensive.Orm/Orm/StorageNode.cs
@@ -72,7 +72,7 @@ public sealed class StorageNode : ISessionSource
///
internal ConcurrentDictionary)> RefsToEntityQueryCache { get; }
internal ConcurrentDictionary KeySequencesCache { get; }
- internal ConcurrentDictionary> PersistRequestCache { get; }
+ internal ConcurrentDictionary> PersistRequestCache { get; } = new();
///
public Session OpenSession() =>
@@ -127,7 +127,6 @@ internal StorageNode(Domain domain, NodeConfiguration configuration, ModelMappin
EntitySetTypeStateCache = new ConcurrentDictionary();
RefsToEntityQueryCache = new ConcurrentDictionary)>();
KeySequencesCache = new ConcurrentDictionary();
- PersistRequestCache = new ConcurrentDictionary>();
this.domain = domain;
Configuration = configuration;
diff --git a/Orm/Xtensive.Orm/Reflection/InterfaceMapping.cs b/Orm/Xtensive.Orm/Reflection/InterfaceMapping.cs
index cf161f4969..548d13ad2f 100644
--- a/Orm/Xtensive.Orm/Reflection/InterfaceMapping.cs
+++ b/Orm/Xtensive.Orm/Reflection/InterfaceMapping.cs
@@ -10,6 +10,7 @@
using ReflectionInterfaceMapping=System.Reflection.InterfaceMapping;
using System.Linq;
using System.Collections.Generic;
+using Xtensive.Core;
namespace Xtensive.Reflection
{
diff --git a/Orm/Xtensive.Orm/Reflection/TypeHelper.cs b/Orm/Xtensive.Orm/Reflection/TypeHelper.cs
index 011c19f2bb..02362d6e7e 100644
--- a/Orm/Xtensive.Orm/Reflection/TypeHelper.cs
+++ b/Orm/Xtensive.Orm/Reflection/TypeHelper.cs
@@ -732,15 +732,15 @@ public static IReadOnlyList GetInterfacesUnordered(Type type) =>
/// The type to get the interfaces of.
[Obsolete("Use GetInterfacesOrderByInheritance instead")]
public static Type[] GetInterfaces(this Type type) =>
- OrderedInterfaces.GetOrAdd(type, t => t.GetInterfaces().OrderByInheritance().ToArray());
+ OrderedInterfaces.GetOrAdd(type, static t => t.GetInterfaces().OrderByInheritance().ToArray());
///
/// Gets the interfaces of the specified type.
/// Interfaces will be ordered from the very base ones to ancestors.
///
/// The type to get the interfaces of.
- public static Type[] GetInterfacesOrderedByInheritance(this Type type) =>
- OrderedInterfaces.GetOrAdd(type, t => t.GetInterfaces().OrderByInheritance().ToArray());
+ public static Type[] GetInterfacesOrderByInheritance(this Type type) =>
+ OrderedInterfaces.GetOrAdd(type, static t => t.GetInterfaces().OrderByInheritance().ToArray());
///
/// Gets the sequence of type itself, all its base types and interfaces.
diff --git a/Orm/Xtensive.Orm/Sorting/Node.cs b/Orm/Xtensive.Orm/Sorting/Node.cs
index e07541db0d..b0900e21b1 100644
--- a/Orm/Xtensive.Orm/Sorting/Node.cs
+++ b/Orm/Xtensive.Orm/Sorting/Node.cs
@@ -10,7 +10,6 @@
using System.Linq;
using Xtensive.Core;
-
namespace Xtensive.Sorting
{
///
@@ -22,9 +21,9 @@ namespace Xtensive.Sorting
public class Node
{
private List> incomingConnections;
- private ReadOnlyCollection> incomingConnectionsReadOnlyList;
+ private IReadOnlyList> incomingConnectionsReadOnlyList;
private List> outgoingConnections;
- private ReadOnlyCollection> outgoingConnectionsReadOnlyList;
+ private IReadOnlyList> outgoingConnectionsReadOnlyList;
///
/// Gets node item.
@@ -164,18 +163,14 @@ public IEnumerable> RemoveConnections
private void EnsureIncomingConnections()
{
- if (incomingConnectionsReadOnlyList==null) {
- incomingConnections = new List>();
- incomingConnectionsReadOnlyList = incomingConnections.AsReadOnly();
- }
+ incomingConnectionsReadOnlyList ??=
+ (incomingConnections = new List>()).AsSafeWrapper();
}
private void EnsureOutgoingConnections()
{
- if (outgoingConnectionsReadOnlyList==null) {
- outgoingConnections = new List>();
- outgoingConnectionsReadOnlyList = outgoingConnections.AsReadOnly();
- }
+ outgoingConnectionsReadOnlyList ??=
+ (outgoingConnections = new List>()).AsSafeWrapper();
}
// Constructors