Skip to content

Commit f1d197a

Browse files
authored
Merge pull request #121 from DataObjects-NET/silent-table-cleanup-issue
Silent table cleanup issue
2 parents c3f8cc4 + 941066e commit f1d197a

15 files changed

+2410
-431
lines changed

Orm/Xtensive.Orm.Tests/Upgrade/UpgradeToNewHierarchyThatInheritsStructureTest.cs

Lines changed: 1632 additions & 0 deletions
Large diffs are not rendered by default.

Orm/Xtensive.Orm/Collections/ClassifiedCollection.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2010-2020 Xtensive LLC.
1+
// Copyright (C) 2010-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Alex Yakunin
@@ -124,6 +124,12 @@ public IEnumerable<TClass> GetClasses()
124124
return classified.Keys;
125125
}
126126

127+
public int GetItemCount(TClass @class)
128+
{
129+
var items = classified.GetValueOrDefault(@class);
130+
return items != null ? items.Count : 0;
131+
}
132+
127133
#region IEnumerable<...> members
128134

129135
IEnumerator IEnumerable.GetEnumerator()

Orm/Xtensive.Orm/Collections/TypeClassifier.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
1+
// Copyright (C) 2010-2021 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Alex Yakunin
@@ -29,6 +29,11 @@ public IEnumerable<TItem> GetItems<TClass>()
2929
return GetItems(typeof (TClass));
3030
}
3131

32+
public int GetItemCount<TClass>()
33+
{
34+
return GetItemCount(typeof(TClass));
35+
}
36+
3237
// Constructors
3338

3439
/// <inheritdoc/>

Orm/Xtensive.Orm/Core/Extensions/CollectionExtensions.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2007-2020 Xtensive LLC.
1+
// Copyright (C) 2007-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Anton U. Rogozhin
@@ -207,5 +207,33 @@ public static IEnumerable<TSource> ReverseList<TSource>(this IList<TSource> sour
207207
for (var i = source.Count - 1; i >= 0; i--)
208208
yield return source[i];
209209
}
210+
211+
/// <summary>
212+
/// Projects each element of a sequence into two elements of new form and adds it to the first or the second array respectively.
213+
/// </summary>
214+
/// <typeparam name="TSource">Type of source sequence.</typeparam>
215+
/// <typeparam name="TFirst">Type of elements of first result array.</typeparam>
216+
/// <typeparam name="TSecond">Type of elements of first result array.</typeparam>
217+
/// <param name="source">A collection of values to invoke a transform functions on.</param>
218+
/// <param name="firstArraySelector">A transform function to apply to each element to get element of the first array.</param>
219+
/// <param name="secondArraySelector">A transform function to apply to each element to get element of the second array.</param>
220+
/// <returns>Pair of two arrays.</returns>
221+
internal static Pair<TFirst[], TSecond[]> SelectToArrays<TSource, TFirst,TSecond>(
222+
this ICollection<TSource> source, Func<TSource, TFirst> firstArraySelector, Func<TSource, TSecond> secondArraySelector)
223+
{
224+
ArgumentValidator.EnsureArgumentNotNull(source, nameof(source));
225+
ArgumentValidator.EnsureArgumentNotNull(firstArraySelector, nameof(firstArraySelector));
226+
ArgumentValidator.EnsureArgumentNotNull(secondArraySelector, nameof(secondArraySelector));
227+
228+
var first = new TFirst[source.Count];
229+
var second = new TSecond[source.Count];
230+
var index = 0;
231+
foreach (var item in source) {
232+
first[index] = firstArraySelector(item);
233+
second[index] = secondArraySelector(item);
234+
index++;
235+
}
236+
return new Pair<TFirst[], TSecond[]>(first, second);
237+
}
210238
}
211239
}

Orm/Xtensive.Orm/Core/Extensions/EnumerableExtensions.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,104 @@ public static List<TItem> ToList<TItem>(this IEnumerable<TItem> source, int capa
291291
return result;
292292
}
293293

294+
/// <summary>
295+
/// Creates a <see cref="Dictionary{TKey, TValue}"/> with pre-defined capacity from an <see cref="IEnumerable{T}"/>
296+
/// according to a specified key selector function.
297+
/// </summary>
298+
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
299+
/// <typeparam name="TKey">The type of the key elements.</typeparam>
300+
/// <param name="source">A sequence to create a <see cref="Dictionary{TKey, TValue}"/> from.</param>
301+
/// <param name="keySelector">A function to extract a key from each element.</param>
302+
/// <param name="capacity">Initial dictionary capacity.</param>
303+
/// <returns>A <see cref="Dictionary{TKey, TValue}"/> that contains keys and values.</returns>
304+
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, int capacity)
305+
{
306+
return ToDictionary<TSource, TKey, TSource>(source, keySelector, InstanceSelector, capacity);
307+
308+
static TSource InstanceSelector(TSource x)
309+
{
310+
return x;
311+
}
312+
}
313+
314+
/// <summary>
315+
/// Creates a <see cref="Dictionary{TKey, TValue}"/> with pre-defined capacity from an <see cref="IEnumerable{T}"/>
316+
/// according to a specified key selector function.
317+
/// </summary>
318+
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
319+
/// <typeparam name="TKey">The type of the key elements.</typeparam>
320+
/// <param name="source">A sequence to create a <see cref="Dictionary{TKey, TValue}"/> from.</param>
321+
/// <param name="keySelector">A function to extract a key from each element.</param>
322+
/// <param name="comparer">An <see cref="IEqualityComparer{T}"/> to compare keys.</param>
323+
/// <param name="capacity">Initial dictionary capacity.</param>
324+
/// <returns>A <see cref="Dictionary{TKey, TValue}"/> that contains keys and values.</returns>
325+
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
326+
this IEnumerable<TSource> source,
327+
Func<TSource, TKey> keySelector,
328+
IEqualityComparer<TKey> comparer,
329+
int capacity)
330+
{
331+
return ToDictionary<TSource, TKey, TSource>(source, keySelector, InstanceSelector, comparer, capacity);
332+
333+
static TSource InstanceSelector(TSource x)
334+
{
335+
return x;
336+
}
337+
}
338+
339+
/// <summary>
340+
/// Creates a <see cref="Dictionary{TKey, TValue}"/> with pre-defined capacity from an <see cref="IEnumerable{T}"/>
341+
/// according to a specified key selector function.
342+
/// </summary>
343+
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
344+
/// <typeparam name="TKey">The type of the key elements.</typeparam>
345+
/// <param name="source">A sequence to create a <see cref="Dictionary{TKey, TValue}"/> from.</param>
346+
/// <param name="keySelector">A function to extract a key from each element.</param>
347+
/// <param name="elementSelector">A funtion to extract a value from each element.</param>
348+
/// <param name="capacity">Initial dictionary capacity.</param>
349+
/// <returns>A <see cref="Dictionary{TKey, TValue}"/> that contains keys and values.</returns>
350+
public static Dictionary<TKey, TValue> ToDictionary<TSource, TKey, TValue>(
351+
this IEnumerable<TSource> source,
352+
Func<TSource, TKey> keySelector,
353+
Func<TSource, TValue> elementSelector,
354+
int capacity)
355+
{
356+
return ToDictionary(source, keySelector, elementSelector, null, capacity);
357+
}
358+
359+
/// <summary>
360+
/// Creates a <see cref="Dictionary{TKey, TValue}"/> with pre-defined capacity from an <see cref="IEnumerable{T}"/>
361+
/// according to a specified key selector function.
362+
/// </summary>
363+
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
364+
/// <typeparam name="TKey">The type of the key elements.</typeparam>
365+
/// <param name="source">A sequence to create a <see cref="Dictionary{TKey, TValue}"/> from.</param>
366+
/// <param name="keySelector">A function to extract a key from each element.</param>
367+
/// <param name="elementSelector">A funtion to extract a value from each element.</param>
368+
/// <param name="comparer">An <see cref="IEqualityComparer{T}"/> to compare keys.</param>
369+
/// <param name="capacity">Initial dictionary capacity.</param>
370+
/// <returns>A <see cref="Dictionary{TKey, TValue}"/> that contains keys and values.</returns>
371+
public static Dictionary<TKey, TValue> ToDictionary<TSource, TKey, TValue>(
372+
this IEnumerable<TSource> source,
373+
Func<TSource, TKey> keySelector,
374+
Func<TSource, TValue> elementSelector,
375+
IEqualityComparer<TKey> equalityComparer,
376+
int capacity)
377+
{
378+
ArgumentValidator.EnsureArgumentNotNull(source, nameof(source));
379+
ArgumentValidator.EnsureArgumentNotNull(keySelector, nameof(keySelector));
380+
ArgumentValidator.EnsureArgumentNotNull(elementSelector, nameof(elementSelector));
381+
ArgumentValidator.EnsureArgumentIsGreaterThanOrEqual(capacity, 0, nameof(capacity));
382+
383+
var dictionary = equalityComparer != null
384+
? new Dictionary<TKey, TValue>(capacity, equalityComparer)
385+
: new Dictionary<TKey, TValue>(capacity);
386+
foreach (var item in source) {
387+
dictionary.Add(keySelector(item), elementSelector(item));
388+
}
389+
return dictionary;
390+
}
391+
294392
/// <summary>
295393
/// Gets the items from the segment.
296394
/// </summary>

Orm/Xtensive.Orm/Modelling/Comparison/Comparer.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Alex Yakunin
@@ -228,6 +228,10 @@ protected virtual MovementInfo BuildMovementInfo(Node source, Node target)
228228
return movementInfo;
229229
}
230230

231+
var recreateHint = Hints.GetHint<RecreateTableHint>(source);
232+
if (recreateHint != null) {
233+
movementInfo |= MovementInfo.Removed | MovementInfo.Created;// recreated;
234+
}
231235
var sc = StringComparer.OrdinalIgnoreCase;
232236

233237
// both source!=null && target!=null
@@ -611,9 +615,9 @@ protected bool HasDataChangeHint(Node source)
611615
return false;
612616

613617
return
614-
Hints.GetHints<CopyDataHint>(source).Any()
615-
|| Hints.GetHints<DeleteDataHint>(source).Any()
616-
|| Hints.GetHints<UpdateDataHint>(source).Any();
618+
Hints.HasHints<CopyDataHint>(source)
619+
|| Hints.HasHints<DeleteDataHint>(source)
620+
|| Hints.HasHints<UpdateDataHint>(source);
617621
}
618622

619623
/// <summary>

Orm/Xtensive.Orm/Modelling/Comparison/Hints/HintSet.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
1+
// Copyright (C) 2009-2021 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Alex Yakunin
@@ -188,6 +188,17 @@ public bool HasHints(Node node)
188188
return nodeHintMap.Values.Count > 0;
189189
}
190190

191+
public bool HasHints<THint>(Node node)
192+
where THint : Hint
193+
{
194+
ArgumentValidator.EnsureArgumentNotNull(node, "node");
195+
196+
if (!hintMap.TryGetValue(node, out var nodeHintMap)) {
197+
hintMap.Add(node, nodeHintMap = new Dictionary<Type, object>());
198+
}
199+
return nodeHintMap.ContainsKey(typeof(THint));
200+
}
201+
191202
#region IEnumerable<...> methods
192203

193204
/// <inheritdoc/>
@@ -247,4 +258,4 @@ private HintSet()
247258
{
248259
}
249260
}
250-
}
261+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (C) 2021 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Text;
8+
9+
namespace Xtensive.Modelling.Comparison.Hints
10+
{
11+
/// <summary>
12+
/// Hints comparer that the table is recreated.
13+
/// How to treat it is up to comparer.
14+
/// </summary>
15+
[Serializable]
16+
public sealed class RecreateTableHint : Hint
17+
{
18+
/// <summary>
19+
/// Path to the table.
20+
/// </summary>
21+
public string Path { get; private set; }
22+
23+
/// <inheritdoc/>
24+
public override IEnumerable<HintTarget> GetTargets()
25+
{
26+
yield return new HintTarget(ModelType.Source, Path);
27+
yield return new HintTarget(ModelType.Target, Path);
28+
}
29+
30+
public override string ToString() => $"Recreate '{Path}'";
31+
32+
public RecreateTableHint(string path)
33+
{
34+
Path = path;
35+
}
36+
}
37+
}

Orm/Xtensive.Orm/Orm/Upgrade/Internals/Extensions/DomainModelExtensions.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)