From 1a99c0ff71b51d97a5f7e1122d07c821cc86920b Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Thu, 31 Oct 2024 19:26:02 +0500 Subject: [PATCH 01/23] Improved tests of string operations' compilers Also moved String members compiler tests from Linq.SelectTest to proper class --- Orm/Xtensive.Orm.Tests/Linq/SelectTest.cs | 112 ---- .../Providers/Sql/StringOperationsTest.cs | 531 ++++++++++++++++-- 2 files changed, 499 insertions(+), 144 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Linq/SelectTest.cs b/Orm/Xtensive.Orm.Tests/Linq/SelectTest.cs index 0c218e418d..92a9454fee 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/SelectTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/SelectTest.cs @@ -768,118 +768,6 @@ where invoice.InvoiceId > 0 && invoice.InvoiceId < 50 } } - [Test] - public void SelectStringIndexerTest() - { - var result = - Session.Query.All() - .Select(c => new { - String = c.CustomerId, - Char0 = c.Email[0], - Char1 = c.Email[1], - Char2 = c.Email[2], - Char3 = c.Email[3], - Char4 = c.Email[4], - }) - .ToArray() - .OrderBy(item => item.String) - .ToArray(); - var expected = Customers - .Select(c => new { - String = c.CustomerId, - Char0 = c.Email[0], - Char1 = c.Email[1], - Char2 = c.Email[2], - Char3 = c.Email[3], - Char4 = c.Email[4], - }) - .OrderBy(item => item.String) - .ToArray(); - Assert.AreEqual(expected.Length, result.Length); - for (var i = 0; i < expected.Length; i++) { - Assert.AreEqual(expected[0].String, result[0].String); - Assert.AreEqual(expected[0].Char0, result[0].Char0); - Assert.AreEqual(expected[0].Char1, result[0].Char1); - Assert.AreEqual(expected[0].Char2, result[0].Char2); - Assert.AreEqual(expected[0].Char3, result[0].Char3); - Assert.AreEqual(expected[0].Char4, result[0].Char4); - } - } - - [Test] - public void SelectIndexOfTest() - { - var _char = 'A'; - var result = - Session.Query.All() - .Select(c => new { - String = c.FirstName, - IndexOfChar = c.FirstName.IndexOf(_char), - IndexOfCharStart = c.FirstName.IndexOf(_char, 1), - IndexOfCharStartCount = c.FirstName.IndexOf(_char, 1, 1), - IndexOfString = c.FirstName.IndexOf(_char.ToString()), - IndexOfStringStart = c.FirstName.IndexOf(_char.ToString(), 1), - IndexOfStringStartCount = c.FirstName.IndexOf(_char.ToString(), 1, 1) - }) - .ToArray() - .OrderBy(item => item.String) - .ToArray(); - var expected = Customers - .Select(c => new { - String = c.FirstName, - IndexOfChar = c.FirstName.IndexOf(_char), - IndexOfCharStart = c.FirstName.IndexOf(_char, 1), - IndexOfCharStartCount = c.FirstName.IndexOf(_char, 1, 1), - IndexOfString = c.FirstName.IndexOf(_char.ToString()), - IndexOfStringStart = c.FirstName.IndexOf(_char.ToString(), 1), - IndexOfStringStartCount = c.FirstName.IndexOf(_char.ToString(), 1, 1) - }) - .OrderBy(item => item.String) - .ToArray(); - Assert.AreEqual(expected.Length, result.Length); - for (var i = 0; i < expected.Length; i++) { - Assert.AreEqual(expected[i].String, result[i].String); - Assert.AreEqual(expected[i].IndexOfChar, result[i].IndexOfChar); - Assert.AreEqual(expected[i].IndexOfCharStart, result[i].IndexOfCharStart); - Assert.AreEqual(expected[i].IndexOfCharStartCount, result[i].IndexOfCharStartCount); - Assert.AreEqual(expected[i].IndexOfString, result[i].IndexOfString); - Assert.AreEqual(expected[i].IndexOfStringStart, result[i].IndexOfStringStart); - Assert.AreEqual(expected[i].IndexOfStringStartCount, result[i].IndexOfStringStartCount); - } - } - - [Test] - public void SelectStringContainsTest1() - { - Require.ProviderIs(StorageProvider.Sqlite | StorageProvider.SqlServer | StorageProvider.MySql); - var result = - Session.Query.All() - .Where(c => c.FirstName.Contains('L')) - .OrderBy(c => c.CustomerId) - .ToArray(); - var expected = Customers - .Where(c => c.FirstName.Contains('L') || c.FirstName.Contains('l')) - .OrderBy(c => c.CustomerId) - .ToArray(); - Assert.IsTrue(expected.SequenceEqual(result)); - } - - [Test] - public void SelectStringContainsTest2() - { - Require.ProviderIsNot(StorageProvider.Sqlite | StorageProvider.SqlServer | StorageProvider.MySql); - var result = - Session.Query.All() - .Where(c => c.FirstName.Contains('L')) - .OrderBy(c => c.CustomerId) - .ToArray(); - var expected = Customers - .Where(c => c.FirstName.Contains('L')) - .OrderBy(c => c.CustomerId) - .ToArray(); - Assert.IsTrue(expected.SequenceEqual(result)); - } - [Test] public void SelectDateTimeTimeSpanTest() { diff --git a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs index 633321395f..81d71f6030 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs @@ -5,6 +5,7 @@ // Created: 2009.07.13 using NUnit.Framework; +using System; using System.Linq; using Xtensive.Orm.Configuration; using Xtensive.Orm.Providers; @@ -15,23 +16,11 @@ namespace Xtensive.Orm.Tests.Storage.Providers.Sql [TestFixture] public class StringOperationsTest : AutoBuildTest { - #region Configuration - - private bool emptyStringIsNull; + private const string StringOfWhiteSpaces = " "; - protected override DomainConfiguration BuildConfiguration() - { - var configuration = base.BuildConfiguration(); - configuration.Types.Register(typeof(X).Assembly, typeof(X).Namespace); - return configuration; - } + #region Configuration - public override void TestFixtureSetUp() - { - base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); - emptyStringIsNull = ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull); - var testValues = new[] { + private readonly string[] testValues = new[] { // test values for TrimStart, TrimEnd, Trim " :-P ", ";-)", @@ -60,15 +49,52 @@ public override void TestFixtureSetUp() "ololo]ololo", "ololoololo]", // other test values - " ", + StringOfWhiteSpaces, }; - foreach (var value in testValues) { + + + private bool emptyStringIsNull; + private bool autoTrimWhiteSpaces; + private bool whitespaceStringAsEmptyString; + + + private Session globalSession; + private TransactionScope globalTransaction; + + + protected override DomainConfiguration BuildConfiguration() + { + var configuration = base.BuildConfiguration(); + configuration.Types.Register(typeof(X).Assembly, typeof(X).Namespace); + return configuration; + } + + public override void TestFixtureSetUp() + { + base.TestFixtureSetUp(); + InitStringRules(); + + var sessionAndTransaction = CreateSessionAndTransaction(); + globalSession = sessionAndTransaction.Item1; + globalTransaction = sessionAndTransaction.Item2; + + var fStrings = emptyStringIsNull ? testValues : testValues.Append(string.Empty); + foreach (var value in fStrings) { _ = new X { FString = value }; } - if (!emptyStringIsNull) { - _ = new X { FString = string.Empty }; - } + globalSession.SaveChanges(); + } + + private void InitStringRules() + { + (emptyStringIsNull, whitespaceStringAsEmptyString, autoTrimWhiteSpaces) = + StorageProviderInfo.Instance.Provider switch { + StorageProvider.Firebird => (ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull), true, true), + StorageProvider.MySql => (ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull), true, false), + StorageProvider.SqlServer => (ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull), true, false), + _ => (ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull), false, false) + }; } #endregion @@ -76,12 +102,51 @@ public override void TestFixtureSetUp() [Test] public void LengthTest() { - var results = Session.Demand().Query.All().Select(x => new { + var results = globalSession.Query.All().Select(x => new { String = x.FString, Length = x.FString.Length }).ToList(); - foreach (var item in results) + foreach (var item in results) { Assert.AreEqual(ConvertString(item.String).Length, item.Length); + } + } + + [Test] + public void LengthServerSideTest() + { + foreach (var value in testValues) { + Assert.That(globalSession.Query.All().Where(x => x.FString == value && x.FString.Length == value.Length).Count(), + Is.EqualTo(1), $"Failed for '{value}'.Length"); + } + } + + [Test] + public void CharsTest() + { + var results = globalSession.Query.All() + .Where(x => x.Id > 5 && x.Id < 11) + .Select(x => new { + String = x.FString, + Char1 = x.FString[1], + Char2 = x.FString[2] + }) + .ToList(); + foreach (var item in results) { + Assert.AreEqual(ConvertString(item.String)[1], item.Char1); + Assert.AreEqual(ConvertString(item.String)[2], item.Char2); + } + } + + [Test] + public void CharsServerSideTest() + { + foreach (var value in testValues.Where(t => t[0] != ' ' && t.Length >= 2)) { + Assert.That(globalSession.Query.All().Where(x => x.FString == value && x.FString[0] == value[0]).Count(), + Is.EqualTo(1), $"Failed for '{value}'[0]"); + + Assert.That(globalSession.Query.All().Where(x => x.FString == value && x.FString[1] == value[1]).Count(), + Is.EqualTo(1), $"Failed for '{value}'[1]"); + } } #region Trim, TrimStart, TrimEnd @@ -89,7 +154,7 @@ public void LengthTest() [Test] public void TrimSpaceTest() { - var results = Session.Demand().Query.All() + var results = globalSession.Query.All() .Select(x => new { String = x.FString, StringTrim = x.FString.Trim(), @@ -115,11 +180,63 @@ public void TrimSpaceTest() } } + [Test] + public void TrimSpaceServerSideTest() + { + var checkForWhitespaceString = StorageProviderInfo.Instance.Provider.HasFlag(StorageProvider.Oracle) + ? (emptyStringIsNull && whitespaceStringAsEmptyString) || autoTrimWhiteSpaces + : emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString; + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && checkForWhitespaceString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Trim() == value.Trim()).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.Trim()"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimStart() == value.TrimStart()).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimStart()"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimEnd() == value.TrimEnd()).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimEnd()"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Trim(null) == value.Trim(null)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.Trim(null)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimStart(null) == value.TrimStart(null)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimStart(null)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimEnd(null) == value.TrimEnd(null)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimEnd(null)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Trim(' ') == value.Trim(' ')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for {value}.Trim(' ')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimStart(' ') == value.TrimStart(' ')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for {value}.TrimStart(' ')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimEnd(' ') == value.TrimEnd(' ')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for {value}.TrimEnd(' ')"); + } + } + [Test] public void TrimOtherCharTest() { - Require.ProviderIsNot(StorageProvider.SqlServer | StorageProvider.SqlServerCe); - var results = Session.Demand().Query.All() + Require.ProviderIsNot( + StorageProvider.SqlServer | StorageProvider.SqlServerCe, + "Can't trim anything except spaces"); + + var results = globalSession.Query.All() .Select(x => new { String = x.FString, StringTrimLeadingLargePLetter = x.FString.TrimStart('P'), @@ -133,19 +250,66 @@ public void TrimOtherCharTest() } } + [Test] + public void TrimOtherCharServerSideTest() + { + Require.ProviderIsNot(StorageProvider.SqlServer | StorageProvider.SqlServerCe); + + var checkForWhitespaceString = StorageProviderInfo.Instance.Provider.HasFlag(StorageProvider.Oracle) + ? (emptyStringIsNull && whitespaceStringAsEmptyString) || autoTrimWhiteSpaces + : emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString; + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && checkForWhitespaceString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimStart('P') == value.TrimStart('P')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimStart('P')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Trim('o') == value.Trim('o')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.Trim('o')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimEnd(')') == value.TrimEnd(')')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimEnd(')')"); + } + } + [Test] public void TrimMultipleCharsTest() { - Require.ProviderIsNot(StorageProvider.SqlServer | StorageProvider.Oracle | StorageProvider.SqlServerCe); - var results = Session.Demand().Query.All() + Require.ProviderIsNot( + StorageProvider.SqlServer | StorageProvider.Oracle | StorageProvider.SqlServerCe | StorageProvider.MySql, + "No support for trimming multiple characters"); + + var results = globalSession.Query.All() .Select(x => new { String = x.FString, StringTrimLeadingZeroAndOne = x.FString.TrimStart('0', '1'), }).ToList(); - foreach (var x in results) + foreach (var x in results) { Assert.AreEqual(ConvertString(x.String).TrimStart('0', '1'), ConvertString(x.StringTrimLeadingZeroAndOne)); + } } + [Test] + public void TrimMultipleCharsServerSideTest() + { + Require.ProviderIsNot( + StorageProvider.SqlServer | StorageProvider.Oracle | StorageProvider.SqlServerCe | StorageProvider.MySql, + "No support for trimming multiple characters"); + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && (emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString) + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.TrimStart('0', '1') == value.TrimStart('0', '1')).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimStart('0', '1')"); + } + } #endregion @@ -154,7 +318,7 @@ public void TrimMultipleCharsTest() [Test] public void StartsWithTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = globalSession.Query.All().Select(x => new { x.Id, String = x.FString, StartsWithA = x.FString.StartsWith("A"), @@ -178,10 +342,55 @@ public void StartsWithTest() } } + [Test] + public void StartsWithServerSideTest() + { + var checkForWhitespaceString = StorageProviderInfo.Instance.Provider.HasFlag(StorageProvider.Oracle) + ? (emptyStringIsNull && whitespaceStringAsEmptyString) || autoTrimWhiteSpaces + : emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString; + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && checkForWhitespaceString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("A") == value.StartsWith("A")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"A\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("%") == value.StartsWith("%")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"%\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("_") == value.StartsWith("_")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"_\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("%_") == value.StartsWith("%_")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"%_\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("_%") == value.StartsWith("_%")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"_%\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("^") == value.StartsWith("^")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"^\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("[") == value.StartsWith("[")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"[\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.StartsWith("]") == value.StartsWith("]")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"]\")"); + } + } + [Test] public void EndsWithTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = globalSession.Query.All().Select(x => new { x.Id, String = x.FString, EndsWithA = x.FString.EndsWith("A"), @@ -205,10 +414,55 @@ public void EndsWithTest() } } + [Test] + public void EndsWithServerSideTest() + { + var checkForWhitespaceString = StorageProviderInfo.Instance.Provider.HasFlag(StorageProvider.Oracle) + ? (emptyStringIsNull && whitespaceStringAsEmptyString) || autoTrimWhiteSpaces + : emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString; + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && checkForWhitespaceString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("A") == value.EndsWith("A")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"A\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("%") == value.EndsWith("%")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"%\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("_") == value.EndsWith("_")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"_\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("%_") == value.EndsWith("%_")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"%_\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("_%") == value.EndsWith("_%")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"_%\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("^") == value.EndsWith("^")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"^\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("[") == value.EndsWith("[")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"[\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("]") == value.EndsWith("]")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"]\")"); + } + } + [Test] public void ContainsTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = globalSession.Query.All().Select(x => new { x.Id, String = x.FString, ContainsA = x.FString.Contains("A"), @@ -232,6 +486,51 @@ public void ContainsTest() } } + [Test] + public void ContainsServerSideTest() + { + var checkForWhitespaceString = StorageProviderInfo.Instance.Provider.HasFlag(StorageProvider.Oracle) + ? (emptyStringIsNull && whitespaceStringAsEmptyString) || autoTrimWhiteSpaces + : emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString; + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && checkForWhitespaceString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("A") == value.Contains("A")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"A\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("%") == value.Contains("%")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"%\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("_") == value.Contains("_")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"_\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("%_") == value.Contains("%_")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"%_\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("_%") == value.Contains("_%")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"_%\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("^") == value.Contains("^")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"^\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.Contains("[") == value.Contains("[")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"[\")"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.EndsWith("]") == value.EndsWith("]")).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.StartsWith(\"]\")"); + } + } + #endregion #region PadLeft, PadRight @@ -239,7 +538,7 @@ public void ContainsTest() [Test] public void PaddingTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = globalSession.Query.All().Select(x => new { x.Id, String = x.FString, PadLeft = x.FString.PadLeft(10), @@ -255,6 +554,174 @@ public void PaddingTest() } } + [Test] + public void PaddingServerSideTest() + { + Require.ProviderIsNot(StorageProvider.Firebird); + + var checkForWhitespaceString = StorageProviderInfo.Instance.Provider.HasFlag(StorageProvider.Oracle) + ? (emptyStringIsNull && whitespaceStringAsEmptyString) || autoTrimWhiteSpaces + : emptyStringIsNull || autoTrimWhiteSpaces || whitespaceStringAsEmptyString; + + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && checkForWhitespaceString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadLeft(10) == value.PadLeft(10)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.PadLeft(10)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadRight(10) == value.PadRight(10)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.PadRight(10)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadLeft(10, 'X') == value.PadLeft(10, 'X')).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadLeft(10, 'X')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadRight(10, 'X') == value.PadRight(10, 'X')).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadRight(10, 'X')"); + } + } + + [Test] + public void PaddingServerSideFirebirdTest() + { + Require.ProviderIs(StorageProvider.Firebird, "Cuts-off length of result string if it is bigger than endlength in LPAD/RPAD"); + + foreach (var value in testValues.Where(s => s != StringOfWhiteSpaces)) { + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadLeft(10) == value.PadLeft(10).Substring(0, 10)).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadLeft(10)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadRight(10) == value.PadRight(10).Substring(0, 10)).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadRight(10)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadLeft(10, 'X') == value.PadLeft(10, 'X').Substring(0, 10)).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadLeft(10, 'X')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadRight(10, 'X') == value.PadRight(10, 'X').Substring(0, 10)).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadRight(10, 'X')"); + } + + foreach (var value in testValues.Where(s => s == StringOfWhiteSpaces)) { + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadLeft(10) == string.Empty.PadLeft(10)).Count(); + Assert.That(result, Is.EqualTo(2), $"Failed for '{value}'.PadLeft(10)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadRight(10) == string.Empty.PadRight(10)).Count(); + Assert.That(result, Is.EqualTo(2), $"Failed for '{value}'.PadRight(10)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadLeft(10, 'X') == string.Empty.PadLeft(10, 'X')).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadLeft(10, 'X')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.PadRight(10, 'X') == string.Empty.PadRight(10, 'X')).Count(); + Assert.That(result, Is.EqualTo(1), $"Failed for '{value}'.PadRight(10, 'X')"); + } + } + + #endregion + + #region IndexOf + + [Test] + public void IndexOfTest() + { + var comparison = StorageProviderInfo.Instance.Provider switch { + StorageProvider.MySql => StringComparison.InvariantCultureIgnoreCase, + StorageProvider.SqlServer => StringComparison.InvariantCultureIgnoreCase, + _ => StringComparison.InvariantCulture + }; + + var _char = 'o'; + var baseQuery = globalSession.Query.All().Where(x => x.FString != string.Empty); + if (emptyStringIsNull || autoTrimWhiteSpaces) { + baseQuery = baseQuery.Where(x => x.FString != null); + } + + var results = baseQuery + .Select(c => new { + String = c.FString, + IndexOfChar = c.FString.IndexOf(_char), + IndexOfCharStart = c.FString.IndexOf(_char, 1), + IndexOfCharStartCount = c.FString.IndexOf(_char, 1, 1), + IndexOfString = c.FString.IndexOf(_char.ToString()), + IndexOfStringStart = c.FString.IndexOf(_char.ToString(), 1), + IndexOfStringStartCount = c.FString.IndexOf(_char.ToString(), 1, 1) + }) + .ToList(); + foreach (var x in results) { + Assert.AreEqual(ConvertString(x.String).IndexOf(_char), x.IndexOfChar); + Assert.AreEqual(ConvertString(x.String).IndexOf(_char, 1), x.IndexOfCharStart); + Assert.AreEqual(ConvertString(x.String).IndexOf(_char, 1, 1), x.IndexOfCharStartCount); + Assert.AreEqual(ConvertString(x.String).IndexOf(_char.ToString()), x.IndexOfString); + Assert.AreEqual(ConvertString(x.String).IndexOf(_char.ToString(), 1), x.IndexOfStringStart); + Assert.AreEqual(ConvertString(x.String).IndexOf(_char.ToString(), 1, 1), x.IndexOfStringStartCount); + } + } + + [Test] + public void IndexOfServerSideTest() + { + Require.ProviderIsNot(StorageProvider.Sqlite, "No support for Position operation."); + + var comparison = StorageProviderInfo.Instance.Provider switch { + StorageProvider.MySql => StringComparison.InvariantCultureIgnoreCase, + StorageProvider.SqlServer => StringComparison.InvariantCultureIgnoreCase, + _ => StringComparison.InvariantCulture + }; + + var _char = 'o'; + foreach (var value in testValues) { + var expectedValue = value == StringOfWhiteSpaces && whitespaceStringAsEmptyString + ? 2 : 1; + + var result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.IndexOf(_char) == value.IndexOf(_char.ToString(), comparison)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.IndexOf(_char)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.IndexOf(_char, 1) == value.IndexOf(_char.ToString(), 1, comparison)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.IndexOf(_char, 1)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.IndexOf(_char, 1, 1) == value.IndexOf(_char.ToString(), 1, 1, comparison)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.TrimStart('0', '1')"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.IndexOf(_char.ToString()) == value.IndexOf(_char.ToString(), comparison)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.IndexOf(_char.ToString())"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.IndexOf(_char.ToString(), 1) == value.IndexOf(_char.ToString(), 1, comparison)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.IndexOf(_char.ToString(), 1)"); + + result = globalSession.Query.All() + .Where(x => x.FString == value && x.FString.IndexOf(_char.ToString(), 1, 1) == value.IndexOf(_char.ToString(), 1, 1, comparison)).Count(); + Assert.That(result, Is.EqualTo(expectedValue), $"Failed for '{value}'.IndexOf(_char.ToString(), 1, 1)"); + } + } + + [Test] + public void IndexOfSqliteServerSideTest() + { + Require.ProviderIs(StorageProvider.Sqlite); + + var _char = 'o'; + var exception = Assert.Throws(() => + globalSession.Query.All() + .Where(x => x.FString.IndexOf(_char) > 0) + .ToList()); + Assert.That(exception.InnerException, Is.InstanceOf()); + } + #endregion private string ConvertString(string value) => From b4022def4e2610332b05331b028213fdcc4a67b4 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 1 Nov 2024 16:03:06 +0500 Subject: [PATCH 02/23] Improve string.Trim/TrimStart/TrimEnd support --- .../MemberCompilers/StringCompilers.cs | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Providers/Expressions/MemberCompilers/StringCompilers.cs b/Orm/Xtensive.Orm/Orm/Providers/Expressions/MemberCompilers/StringCompilers.cs index 9fd23702ab..210c00de27 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/Expressions/MemberCompilers/StringCompilers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/Expressions/MemberCompilers/StringCompilers.cs @@ -139,17 +139,38 @@ public static SqlExpression StringTrim(SqlExpression _this) return SqlDml.Trim(_this); } + [Compiler(typeof(string), nameof(string.TrimStart))] + public static SqlExpression StringTrimStart(SqlExpression _this) + { + return SqlDml.Trim(_this, SqlTrimType.Leading); + } + + [Compiler(typeof(string), nameof(string.TrimEnd))] + public static SqlExpression StringTrimEnd(SqlExpression _this) + { + return SqlDml.Trim(_this, SqlTrimType.Trailing); + } + private static SqlExpression GenericTrim(SqlExpression _this, SqlExpression trimChars, SqlTrimType trimType) { - if (trimChars is SqlNull) + if (trimChars is SqlNull) { return SqlDml.Trim(_this, trimType); - if (!(trimChars is SqlContainer container)) - throw new NotSupportedException(Strings.ExStringTrimSupportedOnlyWithConstants); - if (!(container.Value is char[] chars)) - throw new NotSupportedException(Strings.ExStringTrimSupportedOnlyWithConstants); - return chars.Length==0 - ? SqlDml.Trim(_this, trimType) - : SqlDml.Trim(_this, trimType, new string(chars)); + } + if (trimChars is SqlLiteral oneChar) { + return SqlDml.Trim(_this, trimType, oneChar.Value.ToString()); + } + if (trimChars is SqlContainer container && container.Value is char[] chars) { + if (chars.Length == 0) { + return SqlDml.Trim(_this, trimType); + } + + var context = ExpressionTranslationContext.Current; + var provider = context.ProviderInfo.ProviderName; + return provider.Equals(WellKnown.Provider.Firebird, StringComparison.Ordinal) + ? chars.Aggregate(_this, (current, @char) => SqlDml.Trim(current, trimType, @char.ToString())) + : SqlDml.Trim(_this, trimType, new string(chars)); + } + throw new NotSupportedException(Strings.ExStringTrimSupportedOnlyWithConstants); } [Compiler(typeof(string), nameof(string.Trim))] @@ -159,6 +180,13 @@ public static SqlExpression StringTrim(SqlExpression _this, return GenericTrim(_this, trimChars, SqlTrimType.Both); } + [Compiler(typeof(string), nameof(string.Trim))] + public static SqlExpression StringTrimOneChar(SqlExpression _this, + [Type(typeof(char))] SqlExpression trimChar) + { + return GenericTrim(_this, trimChar, SqlTrimType.Both); + } + [Compiler(typeof(string), nameof(string.TrimStart))] public static SqlExpression StringTrimStart(SqlExpression _this, [Type(typeof(char[]))] SqlExpression trimChars) @@ -166,6 +194,13 @@ public static SqlExpression StringTrimStart(SqlExpression _this, return GenericTrim(_this, trimChars, SqlTrimType.Leading); } + [Compiler(typeof(string), nameof(string.TrimStart))] + public static SqlExpression StringTrimStartOneChar(SqlExpression _this, + [Type(typeof(char))] SqlExpression trimChar) + { + return GenericTrim(_this, trimChar, SqlTrimType.Leading); + } + [Compiler(typeof(string), nameof(string.TrimEnd))] public static SqlExpression StringTrimEnd(SqlExpression _this, [Type(typeof(char[]))] SqlExpression trimChars) @@ -173,6 +208,13 @@ public static SqlExpression StringTrimEnd(SqlExpression _this, return GenericTrim(_this, trimChars, SqlTrimType.Trailing); } + [Compiler(typeof(string), nameof(string.TrimEnd))] + public static SqlExpression StringTrimEndOneChar(SqlExpression _this, + [Type(typeof(char))] SqlExpression trimChar) + { + return GenericTrim(_this, trimChar, SqlTrimType.Trailing); + } + [Compiler(typeof(string), nameof(string.Length), TargetKind.PropertyGet)] public static SqlExpression StringLength(SqlExpression _this) { From bf44a10dbf08b76c1bb2e33e0c09a7af031fef67 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Thu, 26 Dec 2024 19:44:02 +0500 Subject: [PATCH 03/23] MySQL: Fix wrong translation of NullIf --- Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs index 8675b2e563..39b6012e17 100644 --- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs +++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs @@ -101,7 +101,7 @@ public override void Translate(IOutput output, SqlFunctionType type) case SqlFunctionType.CurrentUser: _ = output.Append("CURRENT_USER()"); break; case SqlFunctionType.SessionUser: _ = output.Append("SESSION_USER()"); break; - case SqlFunctionType.NullIf: _ = output.Append("IFNULL"); break; + //case SqlFunctionType.NullIf: _ = output.Append("IFNULL"); break; //datetime/timespan case SqlFunctionType.DateTimeTruncate: _ = output.Append("DATE"); break; case SqlFunctionType.CurrentDate: _ = output.Append("CURDATE()"); break; From 0c0b1d1a24a0d2fe447b8c980dc2198f25702ae9 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 27 Dec 2024 17:18:06 +0500 Subject: [PATCH 04/23] MySQL: Fix Pad operations LPAD/RPAD functions of MySQL requre actual character, so explicitly define whitespace as character. --- .../Sql.Drivers.MySql/v5_0/Compiler.cs | 2 +- Orm/Xtensive.Orm/Sql/SqlHelper.cs | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs index 0a66284582..67413a471a 100644 --- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs +++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs @@ -160,7 +160,7 @@ public override void Visit(SqlFunctionCall node) return; case SqlFunctionType.PadLeft: case SqlFunctionType.PadRight: - SqlHelper.GenericPad(node).AcceptVisitor(this); + SqlHelper.GenericPad(node, true).AcceptVisitor(this); return; case SqlFunctionType.Rand: SqlDml.FunctionCall(translator.TranslateToString(SqlFunctionType.Rand)).AcceptVisitor(this); diff --git a/Orm/Xtensive.Orm/Sql/SqlHelper.cs b/Orm/Xtensive.Orm/Sql/SqlHelper.cs index c9e4a8151c..ebb6f764de 100644 --- a/Orm/Xtensive.Orm/Sql/SqlHelper.cs +++ b/Orm/Xtensive.Orm/Sql/SqlHelper.cs @@ -331,7 +331,7 @@ public static string TimeSpanToString(TimeSpan value, string format) days, hours, minutes, seconds, milliseconds); } - public static SqlExpression GenericPad(SqlFunctionCall node) + public static SqlExpression GenericPad(SqlFunctionCall node, bool padStringRequired = false) { string paddingFunction; switch (node.FunctionType) { @@ -346,9 +346,12 @@ public static SqlExpression GenericPad(SqlFunctionCall node) } var operand = node.Arguments[0]; var result = SqlDml.Case(); - result.Add( - SqlDml.CharLength(operand) < node.Arguments[1], - SqlDml.FunctionCall(paddingFunction, node.Arguments)); + var lenghtCheck = SqlDml.CharLength(operand) < node.Arguments[1]; + var paddingItself = (padStringRequired && node.Arguments.Count < 3) + ? SqlDml.FunctionCall(paddingFunction, operand, node.Arguments[1], SqlDml.Literal(" ")) + : SqlDml.FunctionCall(paddingFunction, node.Arguments); + + _ = result.Add(lenghtCheck, paddingItself); result.Else = operand; return result; } From 36062d4b3aaa3641d18b26eca34bbd5f089079c7 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sat, 28 Dec 2024 17:41:19 +0500 Subject: [PATCH 05/23] SQLite: Fix string.Length translation and implement PadLeft/PadRight operations --- .../Sql.Drivers.Sqlite/v3/Compiler.cs | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs index dc044373f7..14580f4c92 100644 --- a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs +++ b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs @@ -151,10 +151,11 @@ public override void Visit(SqlFunctionCall node) var arguments = node.Arguments; switch (node.FunctionType) { case SqlFunctionType.CharLength: - (SqlDml.FunctionCall("LENGTH", arguments) / 2).AcceptVisitor(this); + SqlDml.FunctionCall("LENGTH", arguments).AcceptVisitor(this); return; case SqlFunctionType.PadLeft: case SqlFunctionType.PadRight: + Visit(EmulateLpadOrRpad(arguments, node.FunctionType is SqlFunctionType.PadLeft)); return; case SqlFunctionType.Concat: var nod = arguments[0]; @@ -631,6 +632,42 @@ private static SqlDateTimePart ConvertDateTimeOffsetPartToDateTimePart(SqlDateTi }; } + private static SqlCase EmulateLpadOrRpad(IReadOnlyList arguments, bool isLpad) + { + var operand = arguments[0]; + var charcount = arguments[1]; + if (charcount is not SqlLiteral intWidth) { + // Since we emulate function with contatination, we need to know total width + // to calculate prefix + throw SqlHelper.NotSupported("PadLeft/PadRight with expressions as total width."); + } + var totalWidth = intWidth.Value; + + var padChar = arguments switch { + _ when arguments.Count == 3 && arguments[2] is SqlLiteral charLiteral => charLiteral.Value, + _ when arguments.Count == 2 => ' ', + _ => throw new NotSupportedException() + }; + + var paddingString = SqlDml.Literal(new string(Enumerable.Repeat(padChar, intWidth.Value).ToArray())); + + var padExpression = isLpad + ? SqlDml.Substring( + SqlDml.Concat(paddingString, operand), + SqlDml.Literal(-totalWidth - 1),// handles '+1' operation in translation of substring function call + SqlDml.Literal(totalWidth)) + : SqlDml.Substring( + SqlDml.Concat(operand, paddingString), + SqlDml.Literal(0), // handles '+1' operation in translation of substring function call + SqlDml.Literal(totalWidth)); + + var @case = SqlDml.Case(); + _ = @case.Add(SqlDml.CharLength(operand) >= charcount, operand); + @case.Else = padExpression; + return @case; + } + + // Constructors /// The driver. From 71e8ef0a00d717cdc11f8d2bf805d50801f69e1b Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Tue, 14 Jan 2025 11:35:47 +0500 Subject: [PATCH 06/23] AutoBuildTest: Introduce GlobalSession/GlobalTransaction for read-only tests --- .../AutoBuildTest.cs | 35 ++- ...Jira0761_ReadingAvgAndSumByDecimalField.cs | 122 ++++---- .../AggregatesProblemTestBase.cs | 7 +- .../Issues/Issue0435_BatchingFail.cs | 16 +- .../Issues/IssueJira0187_TypeCastInContain.cs | 34 +-- ...a0746_LikeBehaviorDifferentOnClientSide.cs | 34 +-- .../Linq/ConvariantQueriesTest.cs | 42 ++- .../Linq/WhereByEnumTest.cs | 3 +- .../Storage/AggregateTest.cs | 263 +++++++++--------- .../CommandProcessorContextProviderTest.cs | 2 +- .../Storage/Providers/Sql/NullValuesTest.cs | 21 +- .../Storage/Providers/Sql/RoundingTest.cs | 57 ++-- .../Providers/Sql/StringOperationsTest.cs | 2 +- .../Storage/TypeCompatibilityTest.cs | 21 +- 14 files changed, 341 insertions(+), 318 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs b/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs index e44a985444..8464df455e 100644 --- a/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs +++ b/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs @@ -19,10 +19,23 @@ public abstract class AutoBuildTest : HasConfigurationAccessTest { private const string ErrorInTestFixtureSetup = "Error in TestFixtureSetUp:\r\n{0}"; private DisposableSet disposables; + private (Session session, TransactionScope transaction) globalSessionAndTransaction; + + /// + /// If set to , global session and transaction will be opened + /// to use one session accross all test methods. + /// + protected virtual bool InitGlobalSession => false; protected ProviderInfo ProviderInfo { get; set; } protected Domain Domain { get; set; } + // Use these two for read-only tests only, don't change them, they are controlled by AutoBuildTest. + // If there is need to change Session/Transactionscope or add/modify/remove entities + // then open dedicated Session/TransactionScope within test + protected Session GlobalSession => InitGlobalSession ? globalSessionAndTransaction.session : throw new Exception("Set UseGlobalSession to true"); + protected TransactionScope GlobalTransaction => InitGlobalSession ? globalSessionAndTransaction.transaction : throw new Exception("Set UseGlobalSession to true"); + [OneTimeSetUp] public virtual void TestFixtureSetUp() { @@ -58,10 +71,16 @@ protected void RebuildDomain() var config = BuildConfiguration(); Domain = BuildDomain(config); - PopulateData(); - - if (Domain!=null) + if (Domain != null) { ProviderInfo = Domain.StorageProviderInfo; + if (InitGlobalSession) { + globalSessionAndTransaction = CreateSessionAndTransaction(); + } + } + else { + ProviderInfo = StorageProviderInfo.Instance.Info; + } + PopulateData(); } protected virtual void PopulateData() @@ -74,8 +93,10 @@ protected virtual void CheckRequirements() protected (Session, TransactionScope) CreateSessionAndTransaction() { + var initDisposable = disposables is null; try { - disposables = new DisposableSet(); + if (initDisposable) + disposables = new DisposableSet(); var session = Domain.OpenSession(); var transaction = session.OpenTransaction(); _ = disposables.Add(session); @@ -83,8 +104,10 @@ protected virtual void CheckRequirements() return (session, transaction); } catch { - disposables.DisposeSafely(); - disposables = null; + if (initDisposable) { + disposables.DisposeSafely(); + disposables = null; + } throw; } } diff --git a/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0761_ReadingAvgAndSumByDecimalField.cs b/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0761_ReadingAvgAndSumByDecimalField.cs index eb0e4a818f..5128bab914 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0761_ReadingAvgAndSumByDecimalField.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0761_ReadingAvgAndSumByDecimalField.cs @@ -164,6 +164,11 @@ public class Order : Entity [Field(Precision = 10, Scale = 0)] public decimal Count { get; set; } + + public Order(Session session) + : base(session) + { + } } } @@ -173,7 +178,7 @@ public class IssueJira0761_ReadingAvgAndSumByDecimalField : AutoBuildTest { private const int OrderCount = 100; - private Session globalSession; + protected override bool InitGlobalSession => true; protected override void CheckRequirements() => Require.ProviderIs(StorageProvider.SqlServer | StorageProvider.PostgreSql); @@ -187,11 +192,8 @@ protected override DomainConfiguration BuildConfiguration() protected override void PopulateData() { - var sAndT = CreateSessionAndTransaction(); - globalSession = sAndT.Item1; - for (var i = 0; i < OrderCount; i++) { - _ = new Order() { + _ = new Order(GlobalSession) { Sum = (i % 2 == 0) ? 100000000000000000000000000.11m : 100000000000000000000000000.12m, Sum2 = 100000000000000000000000000.3m, Sum3 = 10000000000000000000000000.33m, @@ -207,19 +209,19 @@ protected override void PopulateData() } foreach (var i in Enumerable.Range(1, 1000)) { - _ = new ValueByEntityRefCase(globalSession) { - Ref = new DirectFieldValueCase(globalSession) { + _ = new ValueByEntityRefCase(GlobalSession) { + Ref = new DirectFieldValueCase(GlobalSession) { Accepted = 163767 } }; - _ = new KeyValueByEntityRefCase(globalSession) { - Ref = new KeyExpressionCase(globalSession, 163767 + i) + _ = new KeyValueByEntityRefCase(GlobalSession) { + Ref = new KeyExpressionCase(GlobalSession, 163767 + i) }; - _ = new DecimalValueStructureEntityByRefCase(globalSession) { - Ref = new DecimalValueStructureCase(globalSession) { - Struct = new DecimalValueStructure(globalSession) { + _ = new DecimalValueStructureEntityByRefCase(GlobalSession) { + Ref = new DecimalValueStructureCase(GlobalSession) { + Struct = new DecimalValueStructure(GlobalSession) { Value = 163767, Code = i } @@ -227,11 +229,11 @@ protected override void PopulateData() }; } - globalSession.SaveChanges(); + GlobalSession.SaveChanges(); #if DEBUG // just to keep data in database - sAndT.Item2.Complete(); + GlobalTransaction.Complete(); #endif } @@ -240,43 +242,43 @@ protected override void PopulateData() [Test] public void AverageComplexTest() { - var queryResult = globalSession.Query.All().Average(o => o.Sum); + var queryResult = GlobalSession.Query.All().Average(o => o.Sum); var fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.11m).Or.EqualTo(0.12m)); - queryResult = globalSession.Query.All().Average(o => o.Sum2); + queryResult = GlobalSession.Query.All().Average(o => o.Sum2); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.3m)); - queryResult = globalSession.Query.All().Average(o => o.Sum3); + queryResult = GlobalSession.Query.All().Average(o => o.Sum3); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.33m)); - queryResult = globalSession.Query.All().Average(o => o.Sum4); + queryResult = GlobalSession.Query.All().Average(o => o.Sum4); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.333m)); - queryResult = globalSession.Query.All().Average(o => o.Sum5); + queryResult = GlobalSession.Query.All().Average(o => o.Sum5); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.3333m)); - queryResult = globalSession.Query.All().Average(o => o.Sum6); + queryResult = GlobalSession.Query.All().Average(o => o.Sum6); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.33333m)); - queryResult = globalSession.Query.All().Average(o => o.Sum7); + queryResult = GlobalSession.Query.All().Average(o => o.Sum7); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.333333m)); - queryResult = globalSession.Query.All().Average(o => o.Sum8); + queryResult = GlobalSession.Query.All().Average(o => o.Sum8); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.3333333m)); - queryResult = globalSession.Query.All().Average(o => o.Sum9); + queryResult = GlobalSession.Query.All().Average(o => o.Sum9); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.33333333m)); - queryResult = globalSession.Query.All().Average(o => o.Sum10); + queryResult = GlobalSession.Query.All().Average(o => o.Sum10); fraction = queryResult - Math.Floor(queryResult); Assert.That(fraction, Is.EqualTo(0.333333333m)); } @@ -332,10 +334,10 @@ public void AvgDecimalValueStructureEntityByRefCase() [Test] public void AvgDecimalExpressionInSourceExpressionsCase() { - var results = globalSession.Query.All() + var results = GlobalSession.Query.All() .GroupBy(e => e.Id, e => new { Split = e.Accepted * 0.01M }) .Select(g => g.Select(x => x.Split).Distinct().Average()).ToList(); - var localResults = globalSession.Query.All().AsEnumerable() + var localResults = GlobalSession.Query.All().AsEnumerable() .GroupBy(e => e.Id, e => new { Split = e.Accepted * 0.01M }) .Select(g => g.Select(x => x.Split).Distinct().Average()).ToList(); @@ -345,16 +347,16 @@ public void AvgDecimalExpressionInSourceExpressionsCase() private void TestAverage(Expression> selector) where TEntity : Entity { - var results = globalSession.Query.All().Average(selector); - var localResults = globalSession.Query.All().AsEnumerable().Average(selector.Compile()); + var results = GlobalSession.Query.All().Average(selector); + var localResults = GlobalSession.Query.All().AsEnumerable().Average(selector.Compile()); Assert.That(results, Is.EqualTo(localResults), $"Failed on Average({selector})"); - results = globalSession.Query.All().Select(selector).Average(); - localResults = globalSession.Query.All().AsEnumerable().Select(selector.Compile()).Average(); + results = GlobalSession.Query.All().Select(selector).Average(); + localResults = GlobalSession.Query.All().AsEnumerable().Select(selector.Compile()).Average(); Assert.That(results, Is.EqualTo(localResults), $"Failed on Select({selector}).Average()"); - results = globalSession.Query.All().Select(selector).Distinct().Average(); - localResults = globalSession.Query.All().AsEnumerable().Select(selector.Compile()).Distinct().Average(); + results = GlobalSession.Query.All().Select(selector).Distinct().Average(); + localResults = GlobalSession.Query.All().AsEnumerable().Select(selector.Compile()).Distinct().Average(); Assert.That(results, Is.EqualTo(localResults), $"Failed on Select({selector}).Distinct().Average()"); } @@ -367,44 +369,44 @@ public void SumComplexTest() { Require.ProviderIs(StorageProvider.SqlServer, " MS SQL Server has scale reduction algorithm, PgSql doesn't"); - var queryResult = globalSession.Query.All().Sum(o => o.Sum); - var localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum); + var queryResult = GlobalSession.Query.All().Sum(o => o.Sum); + var localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum); Assert.That(queryResult, Is.EqualTo(localResult + 3)); - queryResult = globalSession.Query.All().Sum(o => o.Sum2); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum2); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum2); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum2); Assert.That(queryResult, Is.EqualTo(localResult + 6)); - queryResult = globalSession.Query.All().Sum(o => o.Sum3); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum3); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum3); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum3); Assert.That(queryResult, Is.EqualTo(localResult + 0.6m)); - queryResult = globalSession.Query.All().Sum(o => o.Sum4); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum4); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum4); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum4); Assert.That(queryResult, Is.EqualTo(localResult)); - queryResult = globalSession.Query.All().Sum(o => o.Sum5); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum5); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum5); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum5); Assert.That(queryResult, Is.EqualTo(localResult)); - queryResult = globalSession.Query.All().Sum(o => o.Sum6); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum6); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum6); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum6); Assert.That(queryResult, Is.EqualTo(localResult)); - queryResult = globalSession.Query.All().Sum(o => o.Sum7); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum7); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum7); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum7); Assert.That(queryResult, Is.EqualTo(localResult)); - queryResult = globalSession.Query.All().Sum(o => o.Sum8); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum8); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum8); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum8); Assert.That(queryResult, Is.EqualTo(localResult)); - queryResult = globalSession.Query.All().Sum(o => o.Sum9); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum9); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum9); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum9); Assert.That(queryResult, Is.EqualTo(localResult)); - queryResult = globalSession.Query.All().Sum(o => o.Sum10); - localResult = globalSession.Query.All().ToArray().Sum(o => o.Sum10); + queryResult = GlobalSession.Query.All().Sum(o => o.Sum10); + localResult = GlobalSession.Query.All().ToArray().Sum(o => o.Sum10); Assert.That(queryResult, Is.EqualTo(localResult)); } @@ -459,10 +461,10 @@ public void SumDecimalValueStructureEntityByRefCase() [Test] public void SumDecimalExpressionInSourceExpressionsCase() { - var results = globalSession.Query.All() + var results = GlobalSession.Query.All() .GroupBy(e => e.Id, e => new { Split = e.Accepted * 0.01M }) .Select(g => g.Select(x => x.Split).Distinct().Sum()).ToList(); - var localResults = globalSession.Query.All().AsEnumerable() + var localResults = GlobalSession.Query.All().AsEnumerable() .GroupBy(e => e.Id, e => new { Split = e.Accepted * 0.01M }) .Select(g => g.Select(x => x.Split).Distinct().Sum()).ToList(); @@ -472,16 +474,16 @@ public void SumDecimalExpressionInSourceExpressionsCase() private void TestSum(Expression> selector) where TEntity : Entity { - var results = globalSession.Query.All().Sum(selector); - var localResults = globalSession.Query.All().AsEnumerable().Sum(selector.Compile()); + var results = GlobalSession.Query.All().Sum(selector); + var localResults = GlobalSession.Query.All().AsEnumerable().Sum(selector.Compile()); Assert.That(results, Is.EqualTo(localResults), $"Failed on Sum({selector})"); - results = globalSession.Query.All().Select(selector).Sum(); - localResults = globalSession.Query.All().AsEnumerable().Select(selector.Compile()).Sum(); + results = GlobalSession.Query.All().Select(selector).Sum(); + localResults = GlobalSession.Query.All().AsEnumerable().Select(selector.Compile()).Sum(); Assert.That(results, Is.EqualTo(localResults), $"Failed on Select({selector}).Sum()"); - results = globalSession.Query.All().Select(selector).Distinct().Sum(); - localResults = globalSession.Query.All().AsEnumerable().Select(selector.Compile()).Distinct().Sum(); + results = GlobalSession.Query.All().Select(selector).Distinct().Sum(); + localResults = GlobalSession.Query.All().AsEnumerable().Select(selector.Compile()).Distinct().Sum(); Assert.That(results, Is.EqualTo(localResults), $"Failed on Select({selector}).Distinct().Sum()"); } diff --git a/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0786/AggregatesProblemTestBase.cs b/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0786/AggregatesProblemTestBase.cs index 4a8f49cc5d..7c4c7edcaf 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0786/AggregatesProblemTestBase.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/AggregatesRelatedIssues/IssueJira0786/AggregatesProblemTestBase.cs @@ -15,14 +15,11 @@ namespace Xtensive.Orm.Tests.Issues.IssueJira0786_AggregatesProblem { public abstract class AggregatesProblemTestBase : AutoBuildTest { - private bool refillDatabase = false; - protected decimal FloatValueAccuracy { get; private set; } = 0.000001m; protected decimal DoubleValueAccuracy { get; private set; } = 0.00000000000001m; protected decimal DecimalValueAccuracy { get; private set; } = 0.00000000000000001m; - protected Session GlobalSession { get; private set; } - protected TransactionScope GlobalTransaction { get; private set; } + protected override bool InitGlobalSession => true; protected override DomainConfiguration BuildConfiguration() { @@ -46,8 +43,6 @@ protected override void PopulateData() DecimalValueAccuracy = 0.00001m; } - (GlobalSession, GlobalTransaction) = CreateSessionAndTransaction(); - _ = new TestEntity(GlobalSession) { ByteValue = 2, SByteValue = 4, diff --git a/Orm/Xtensive.Orm.Tests/Issues/Issue0435_BatchingFail.cs b/Orm/Xtensive.Orm.Tests/Issues/Issue0435_BatchingFail.cs index f6a6085110..5d2da33c14 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/Issue0435_BatchingFail.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/Issue0435_BatchingFail.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2009-20223 Xtensive LLC. +// Copyright (C) 2009-2025 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 @@ -28,6 +28,8 @@ namespace Xtensive.Orm.Tests.Issues { public class Issue0435_BatchingFail : AutoBuildTest { + protected override bool InitGlobalSession => true; + protected override DomainConfiguration BuildConfiguration() { var configuration = base.BuildConfiguration(); @@ -35,12 +37,6 @@ protected override DomainConfiguration BuildConfiguration() return configuration; } - public override void TestFixtureSetUp() - { - base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); - } - [Test] public void Test1() { @@ -52,7 +48,7 @@ public void Test1() Text = "Entity 2" }; // Nothing is sent to server yet - foreach (var e in Session.Demand().Query.All()) // Batch is sent + foreach (var e in GlobalSession.Query.All()) // Batch is sent Console.WriteLine("Entity.Text: {0}", e.Text); } @@ -67,9 +63,9 @@ public void Test2() Text = "Entity 2" }; // Nothing is sent to server yet - var futureCount = Session.Demand().Query.CreateDelayedQuery(qe => qe.All().Count()); + var futureCount = GlobalSession.Query.CreateDelayedQuery(qe => qe.All().Count()); - foreach (var e in Session.Demand().Query.All()) // Batch is sent + foreach (var e in GlobalSession.Query.All()) // Batch is sent Console.WriteLine("Entity.Text: {0}", e.Text); Console.WriteLine("Count: {0}", futureCount.Value); } diff --git a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0187_TypeCastInContain.cs b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0187_TypeCastInContain.cs index 0820dc8e8d..2f45ecabf3 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0187_TypeCastInContain.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0187_TypeCastInContain.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2023 Xtensive LLC. +// Copyright (C) 2011-2025 Xtensive LLC. // This code is distributed under MIT license terms. // See the License.txt file in the project root for more information. // Created by: Dmitri Maximov @@ -43,6 +43,8 @@ namespace Xtensive.Orm.Tests.Issues { public class Issue_TypeCastInContain : AutoBuildTest { + protected override bool InitGlobalSession => true; + protected override DomainConfiguration BuildConfiguration() { var config = base.BuildConfiguration(); @@ -50,52 +52,46 @@ protected override DomainConfiguration BuildConfiguration() return config; } - public override void TestFixtureSetUp() - { - base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); - } - [Test] public void ParentsContainsChildWithImplicitCastTest() { - var parents = Query.All().ToArray(); - var result = Query.All().Where(child => parents.Contains(child)).ToArray(); + var parents = GlobalSession.Query.All().ToArray(); + var result = GlobalSession.Query.All().Where(child => parents.Contains(child)).ToArray(); } [Test] public void ParentsContainsChildWithExplicitCastTest() { - var parents = Query.All().ToArray(); - var result = Query.All().Where(child => parents.Contains(child as Parent)).ToArray(); + var parents = GlobalSession.Query.All().ToArray(); + var result = GlobalSession.Query.All().Where(child => parents.Contains(child as Parent)).ToArray(); } [Test] public void ChildInParentsTest() { - var parents = Query.All().ToArray(); - var result = Query.All().Where(child => child.In(parents)).ToArray(); + var parents = GlobalSession.Query.All().ToArray(); + var result = GlobalSession.Query.All().Where(child => child.In(parents)).ToArray(); } [Test] public void ChildContainsParentWithImplicitCast() { - var children = Query.All().ToArray(); - var result = Query.All().Where(a => children.Contains(a.Parent)).ToArray(); + var children = GlobalSession.Query.All().ToArray(); + var result = GlobalSession.Query.All().Where(a => children.Contains(a.Parent)).ToArray(); } [Test] public void ChildContainsParentWithExplicitCast() { - var children = Query.All().ToArray(); - var result = Query.All().Where(a => (children as IEnumerable).Contains(a.Parent)).ToArray(); + var children = GlobalSession.Query.All().ToArray(); + var result = GlobalSession.Query.All().Where(a => (children as IEnumerable).Contains(a.Parent)).ToArray(); } [Test] public void ParentInChildrenTest() { - var children = Query.All().ToArray(); - var result = Query.All().Where(a => a.Parent.In(children)).ToArray(); + var children = GlobalSession.Query.All().ToArray(); + var result = GlobalSession.Query.All().Where(a => a.Parent.In(children)).ToArray(); } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0746_LikeBehaviorDifferentOnClientSide.cs b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0746_LikeBehaviorDifferentOnClientSide.cs index 8c725e7e6e..86dcac14d7 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0746_LikeBehaviorDifferentOnClientSide.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0746_LikeBehaviorDifferentOnClientSide.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2023 Xtensive LLC. +// Copyright (C) 2018-2025 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 Kudelin @@ -21,6 +21,11 @@ public class SimpleEntity : Entity [Field] public string Name { get; set; } + + public SimpleEntity(Session session) + : base(session) + { + } } } @@ -84,11 +89,7 @@ public class IssueJira0746_LikeBehaviorDifferentOnClientSide : AutoBuildTest #endregion - public override void TestFixtureSetUp() - { - base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); - } + protected override bool InitGlobalSession => true; protected override DomainConfiguration BuildConfiguration() { @@ -100,23 +101,19 @@ protected override DomainConfiguration BuildConfiguration() protected override void PopulateData() { - using (var session = Domain.OpenSession()) - using (var transaction = session.OpenTransaction()) { - foreach (var testCase in TestCases) { - _ = new SimpleEntity { Name = testCase }; - } - - transaction.Complete(); + foreach (var testCase in TestCases) { + _ = new SimpleEntity(GlobalSession) { Name = testCase }; } + + GlobalSession.SaveChanges(); } [Test] [TestCaseSource(nameof(HitSearchStrings))] public void HitTest(string searchPattern) { - var session = Session.Current; - var local = session.Query.All().ToArray().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); - var server = session.Query.All().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); + var local = GlobalSession.Query.All().AsEnumerable().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); + var server = GlobalSession.Query.All().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); Assert.That(server.Length, Is.Not.EqualTo(0)); Assert.That(local.Length, Is.EqualTo(server.Length)); @@ -128,9 +125,8 @@ public void HitTest(string searchPattern) [TestCaseSource(nameof(MissSearchStrings))] public void MissTest(string searchPattern) { - var session = Session.Current; - var local = session.Query.All().ToArray().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); - var server = session.Query.All().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); + var local = GlobalSession.Query.All().AsEnumerable().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); + var server = GlobalSession.Query.All().Where(z => z.Name.Like(searchPattern, '&')).OrderBy(e => e.Id).ToArray(); Assert.That(server.Length, Is.EqualTo(0)); Assert.That(local.Length, Is.EqualTo(server.Length)); diff --git a/Orm/Xtensive.Orm.Tests/Linq/ConvariantQueriesTest.cs b/Orm/Xtensive.Orm.Tests/Linq/ConvariantQueriesTest.cs index 33015db847..3e2f7bd1d6 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/ConvariantQueriesTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/ConvariantQueriesTest.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2023 Xtensive LLC. +// Copyright (C) 2011-2025 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 @@ -32,6 +32,8 @@ namespace Xtensive.Orm.Tests.Linq { public class ConvariantQueriesTest : AutoBuildTest { + protected override bool InitGlobalSession => true; + protected override DomainConfiguration BuildConfiguration() { var config = base.BuildConfiguration(); @@ -39,24 +41,18 @@ protected override DomainConfiguration BuildConfiguration() return config; } - public override void TestFixtureSetUp() - { - base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); - } - [Test] public void ConcatTest() { - var q1 = Query.All().Concat(Query.All()).ToList(); - var q2 = Query.All().Concat(Query.All()).ToList(); + var q1 = GlobalSession.Query.All().Concat(GlobalSession.Query.All()).ToList(); + var q2 = GlobalSession.Query.All().Concat(GlobalSession.Query.All()).ToList(); } [Test] public void UnionTest() { - var q1 = Query.All().Union(Query.All()).ToList(); - var q2 = Query.All().Union(Query.All()).ToList(); + var q1 = GlobalSession.Query.All().Union(GlobalSession.Query.All()).ToList(); + var q2 = GlobalSession.Query.All().Union(GlobalSession.Query.All()).ToList(); } [Test] @@ -64,8 +60,8 @@ public void IntersectTest() { //some storages does not support Intersect operation Require.ProviderIsNot(StorageProvider.Firebird | StorageProvider.MySql); - var q1 = Query.All().Intersect(Query.All()).ToList(); - var q2 = Query.All().Intersect(Query.All()).ToList(); + var q1 = GlobalSession.Query.All().Intersect(GlobalSession.Query.All()).ToList(); + var q2 = GlobalSession.Query.All().Intersect(GlobalSession.Query.All()).ToList(); } [Test] @@ -73,29 +69,29 @@ public void ExceptTest() { //Some storages does not support Except operation Require.ProviderIsNot(StorageProvider.Firebird | StorageProvider.MySql); - var q1 = Query.All().Except(Query.All()).ToList(); - var q2 = Query.All().Except(Query.All()).ToList(); + var q1 = GlobalSession.Query.All().Except(GlobalSession.Query.All()).ToList(); + var q2 = GlobalSession.Query.All().Except(GlobalSession.Query.All()).ToList(); } [Test] public void ContainsTest() { - var q1 = Query.All() - .Where(baseEntity => Query.All().Contains(baseEntity)) + var q1 = GlobalSession.Query.All() + .Where(baseEntity => GlobalSession.Query.All().Contains(baseEntity)) .ToList(); - var q2 = Query.All() - .Where(childEntity => Query.All().Contains(childEntity)) + var q2 = GlobalSession.Query.All() + .Where(childEntity => GlobalSession.Query.All().Contains(childEntity)) .ToList(); } [Test] public void InTest() { - var q1 = Query.All() - .Where(baseEntity => baseEntity.In(Query.All())) + var q1 = GlobalSession.Query.All() + .Where(baseEntity => baseEntity.In(GlobalSession.Query.All())) .ToList(); - var q2 = Query.All() - .Where(childEntity => childEntity.In(Query.All())) + var q2 = GlobalSession.Query.All() + .Where(childEntity => childEntity.In(GlobalSession.Query.All())) .ToList(); } } diff --git a/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs b/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs index c2e6063f9f..03c725d8f3 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs @@ -171,8 +171,7 @@ public class WhereByEnumTest : AutoBuildTest public override void TestFixtureSetUp() { base.TestFixtureSetUp(); - CreateSessionAndTransaction(); - sharedSession = Session.Current; + sharedSession = CreateSessionAndTransaction().Item1; castSign = StorageProviderInfo.Instance.CheckProviderIs(StorageProvider.PostgreSql) ? "::" : "CAST"; diff --git a/Orm/Xtensive.Orm.Tests/Storage/AggregateTest.cs b/Orm/Xtensive.Orm.Tests/Storage/AggregateTest.cs index 6bacdfecb9..846e5319d1 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/AggregateTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/AggregateTest.cs @@ -18,8 +18,8 @@ namespace Xtensive.Orm.Tests.Storage public class AggregateTest : AutoBuildTest { private List all; - private Session globalSession; - private TransactionScope globalTransaction; + + protected override bool InitGlobalSession => true; protected override DomainConfiguration BuildConfiguration() { @@ -32,7 +32,6 @@ public override void TestFixtureSetUp() { base.TestFixtureSetUp(); - (globalSession, globalTransaction) = CreateSessionAndTransaction(); all = new List(); for (var i = 0; i < 10; i++) { @@ -54,50 +53,50 @@ public override void TestFixtureSetUp() all.Add(x); } - globalSession.SaveChanges(); + GlobalSession.SaveChanges(); } [Test] public void SumTest() { - Assert.AreEqual(all.Sum(x => x.FByte), globalSession.Query.All().Sum(x => x.FByte), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Sum(x => x.FSByte), globalSession.Query.All().Sum(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Sum(x => x.FByte), GlobalSession.Query.All().Sum(x => x.FByte), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Sum(x => x.FSByte), GlobalSession.Query.All().Sum(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Sum(x => x.FShort), globalSession.Query.All().Sum(x => x.FShort), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Sum(x => x.FUShort), globalSession.Query.All().Sum(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Sum(x => x.FShort), GlobalSession.Query.All().Sum(x => x.FShort), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Sum(x => x.FUShort), GlobalSession.Query.All().Sum(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Sum(x => x.FInt), globalSession.Query.All().Sum(x => x.FInt), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Sum(x => x.FUInt), globalSession.Query.All().Sum(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Sum(x => x.FInt), GlobalSession.Query.All().Sum(x => x.FInt), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Sum(x => x.FUInt), GlobalSession.Query.All().Sum(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Sum(x => x.FLong), globalSession.Query.All().Sum(x => x.FLong), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Sum(x => x.FFloat), globalSession.Query.All().Sum(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Sum(x => x.FDecimal), globalSession.Query.All().Sum(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Sum(x => x.FLong), GlobalSession.Query.All().Sum(x => x.FLong), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Sum(x => x.FFloat), GlobalSession.Query.All().Sum(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Sum(x => x.FDecimal), GlobalSession.Query.All().Sum(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); } [Test] public void SumNoLambdaTest() { - Assert.AreEqual(all.Sum(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Sum(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Sum(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Sum(), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Sum(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Sum(), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Sum(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Sum(), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Sum(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Sum(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Sum(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Sum(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Sum(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Sum(), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Sum(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Sum(), $"Failed for {nameof(X.FDecimal)}"); } [Test] public void SumByValueItselfTest() { - Assert.AreEqual(all.Sum(x => x.FByte), globalSession.Query.All().Select(x => x.FByte).Sum(x => x), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Sum(x => x.FSByte), globalSession.Query.All().Select(x => x.FSByte).Sum(x => x), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Sum(x => x.FByte), GlobalSession.Query.All().Select(x => x.FByte).Sum(x => x), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Sum(x => x.FSByte), GlobalSession.Query.All().Select(x => x.FSByte).Sum(x => x), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Sum(x => x.FShort), globalSession.Query.All().Select(x => x.FShort).Sum(x => x), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Sum(x => x.FUShort), globalSession.Query.All().Select(x => x.FUShort).Sum(x => x), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Sum(x => x.FShort), GlobalSession.Query.All().Select(x => x.FShort).Sum(x => x), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Sum(x => x.FUShort), GlobalSession.Query.All().Select(x => x.FUShort).Sum(x => x), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Sum(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Sum(x => x), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Sum(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Sum(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Sum(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Sum(x => x), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Sum(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Sum(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Sum(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Sum(x => x), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Sum(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Sum(x => x), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Sum(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Sum(x => x), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Sum(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Sum(x => x), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Sum(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Sum(x => x), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Sum(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Sum(x => x), $"Failed for {nameof(X.FDecimal)}"); } @@ -109,26 +108,26 @@ public void AverageTest() // © Firebird documentation // Funny, isn't it? if (Domain.Configuration.ConnectionInfo.Provider==WellKnown.Provider.Firebird) { - Assert.AreEqual(Math.Truncate(all.Average(x => x.FByte)), globalSession.Query.All().Average(x => x.FByte), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FSByte)), globalSession.Query.All().Average(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FShort)), globalSession.Query.All().Average(x => x.FShort), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FUShort)), globalSession.Query.All().Average(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FInt)), globalSession.Query.All().Average(x => x.FInt), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FUInt)), globalSession.Query.All().Average(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FLong)), globalSession.Query.All().Average(x => x.FLong), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FByte)), GlobalSession.Query.All().Average(x => x.FByte), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FSByte)), GlobalSession.Query.All().Average(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FShort)), GlobalSession.Query.All().Average(x => x.FShort), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FUShort)), GlobalSession.Query.All().Average(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FInt)), GlobalSession.Query.All().Average(x => x.FInt), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FUInt)), GlobalSession.Query.All().Average(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FLong)), GlobalSession.Query.All().Average(x => x.FLong), $"Failed for {nameof(X.FLong)}"); } else { - Assert.AreEqual(all.Average(x => x.FByte), globalSession.Query.All().Average(x => x.FByte), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Average(x => x.FSByte), globalSession.Query.All().Average(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Average(x => x.FShort), globalSession.Query.All().Average(x => x.FShort), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Average(x => x.FUShort), globalSession.Query.All().Average(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Average(x => x.FInt), globalSession.Query.All().Average(x => x.FInt), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Average(x => x.FUInt), globalSession.Query.All().Average(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Average(x => x.FLong), globalSession.Query.All().Average(x => x.FLong), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Average(x => x.FByte), GlobalSession.Query.All().Average(x => x.FByte), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Average(x => x.FSByte), GlobalSession.Query.All().Average(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Average(x => x.FShort), GlobalSession.Query.All().Average(x => x.FShort), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Average(x => x.FUShort), GlobalSession.Query.All().Average(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Average(x => x.FInt), GlobalSession.Query.All().Average(x => x.FInt), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Average(x => x.FUInt), GlobalSession.Query.All().Average(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Average(x => x.FLong), GlobalSession.Query.All().Average(x => x.FLong), $"Failed for {nameof(X.FLong)}"); } - Assert.AreEqual(all.Average(x => x.FFloat), globalSession.Query.All().Average(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Average(x => x.FDecimal), globalSession.Query.All().Average(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Average(x => x.FFloat), GlobalSession.Query.All().Average(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Average(x => x.FDecimal), GlobalSession.Query.All().Average(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); } [Test] @@ -139,18 +138,18 @@ public void AverageNoLambdaTest() // © Firebird documentation // Funny, isn't it? if (Domain.Configuration.ConnectionInfo.Provider == WellKnown.Provider.Firebird) { - Assert.AreEqual(Math.Truncate(all.Average(x => x.FInt)), globalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FUInt)), globalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FLong)), globalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FInt)), GlobalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FUInt)), GlobalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FLong)), GlobalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); } else { - Assert.AreEqual(all.Average(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Average(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Average(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Average(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Average(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Average(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); } - Assert.AreEqual(all.Average(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Average(), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Average(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Average(), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Average(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Average(), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Average(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Average(), $"Failed for {nameof(X.FDecimal)}"); } [Test] @@ -161,146 +160,146 @@ public void AverageByValueItselfTest() // © Firebird documentation // Funny, isn't it? if (Domain.Configuration.ConnectionInfo.Provider == WellKnown.Provider.Firebird) { - Assert.AreEqual(Math.Truncate(all.Average(x => x.FByte)), globalSession.Query.All().Select(x => x.FByte).Average(x => x), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FSByte)), globalSession.Query.All().Select(x => x.FSByte).Average(x => x), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FShort)), globalSession.Query.All().Select(x => x.FShort).Average(x => x), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FUShort)), globalSession.Query.All().Select(x => x.FUShort).Average(x => x), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FInt)), globalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FUInt)), globalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(Math.Truncate(all.Average(x => x.FLong)), globalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FByte)), GlobalSession.Query.All().Select(x => x.FByte).Average(x => x), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FSByte)), GlobalSession.Query.All().Select(x => x.FSByte).Average(x => x), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FShort)), GlobalSession.Query.All().Select(x => x.FShort).Average(x => x), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FUShort)), GlobalSession.Query.All().Select(x => x.FUShort).Average(x => x), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FInt)), GlobalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FUInt)), GlobalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(Math.Truncate(all.Average(x => x.FLong)), GlobalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); } else { - Assert.AreEqual(all.Average(x => x.FByte), globalSession.Query.All().Select(x => x.FByte).Average(x => x), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Average(x => x.FSByte), globalSession.Query.All().Select(x => x.FSByte).Average(x => x), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Average(x => x.FShort), globalSession.Query.All().Select(x => x.FShort).Average(x => x), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Average(x => x.FUShort), globalSession.Query.All().Select(x => x.FUShort).Average(x => x), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Average(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Average(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Average(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Average(x => x.FByte), GlobalSession.Query.All().Select(x => x.FByte).Average(x => x), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Average(x => x.FSByte), GlobalSession.Query.All().Select(x => x.FSByte).Average(x => x), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Average(x => x.FShort), GlobalSession.Query.All().Select(x => x.FShort).Average(x => x), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Average(x => x.FUShort), GlobalSession.Query.All().Select(x => x.FUShort).Average(x => x), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Average(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Average(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Average(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Average(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Average(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Average(), $"Failed for {nameof(X.FLong)}"); } - Assert.AreEqual(all.Average(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Average(), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Average(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Average(), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Average(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Average(), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Average(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Average(), $"Failed for {nameof(X.FDecimal)}"); } [Test] public void MinTest() { - Assert.AreEqual(all.Min(x => x.FByte), globalSession.Query.All().Min(x => x.FByte), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Min(x => x.FSByte), globalSession.Query.All().Min(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Min(x => x.FByte), GlobalSession.Query.All().Min(x => x.FByte), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Min(x => x.FSByte), GlobalSession.Query.All().Min(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Min(x => x.FShort), globalSession.Query.All().Min(x => x.FShort), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Min(x => x.FUShort), globalSession.Query.All().Min(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Min(x => x.FShort), GlobalSession.Query.All().Min(x => x.FShort), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Min(x => x.FUShort), GlobalSession.Query.All().Min(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Min(x => x.FInt), globalSession.Query.All().Min(x => x.FInt), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Min(x => x.FUInt), globalSession.Query.All().Min(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Min(x => x.FInt), GlobalSession.Query.All().Min(x => x.FInt), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Min(x => x.FUInt), GlobalSession.Query.All().Min(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Min(x => x.FLong), globalSession.Query.All().Min(x => x.FLong), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Min(x => x.FFloat), globalSession.Query.All().Min(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Min(x => x.FDecimal), globalSession.Query.All().Min(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Min(x => x.FLong), GlobalSession.Query.All().Min(x => x.FLong), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Min(x => x.FFloat), GlobalSession.Query.All().Min(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Min(x => x.FDecimal), GlobalSession.Query.All().Min(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); - Assert.AreEqual(all.Min(x => x.FDateTime), globalSession.Query.All().Min(x => x.FDateTime), $"Failed for {nameof(X.FDateTime)}"); - Assert.AreEqual(all.Min(x => x.FTimeSpan), globalSession.Query.All().Min(x => x.FTimeSpan), $"Failed for {nameof(X.FTimeSpan)}"); + Assert.AreEqual(all.Min(x => x.FDateTime), GlobalSession.Query.All().Min(x => x.FDateTime), $"Failed for {nameof(X.FDateTime)}"); + Assert.AreEqual(all.Min(x => x.FTimeSpan), GlobalSession.Query.All().Min(x => x.FTimeSpan), $"Failed for {nameof(X.FTimeSpan)}"); } [Test] public void MinNoLambdaTest() { - Assert.AreEqual(all.Min(x => x.FByte), globalSession.Query.All().Select(x => x.FByte).Min(), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Min(x => x.FSByte), globalSession.Query.All().Select(x => x.FSByte).Min(), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Min(x => x.FByte), GlobalSession.Query.All().Select(x => x.FByte).Min(), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Min(x => x.FSByte), GlobalSession.Query.All().Select(x => x.FSByte).Min(), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Min(x => x.FShort), globalSession.Query.All().Select(x => x.FShort).Min(), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Min(x => x.FUShort), globalSession.Query.All().Select(x => x.FUShort).Min(), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Min(x => x.FShort), GlobalSession.Query.All().Select(x => x.FShort).Min(), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Min(x => x.FUShort), GlobalSession.Query.All().Select(x => x.FUShort).Min(), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Min(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Min(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Min(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Min(), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Min(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Min(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Min(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Min(), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Min(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Min(), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Min(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Min(), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Min(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Min(), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Min(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Min(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Min(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Min(), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Min(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Min(), $"Failed for {nameof(X.FDecimal)}"); - Assert.AreEqual(all.Min(x => x.FDateTime), globalSession.Query.All().Select(x => x.FDateTime).Min(), $"Failed for {nameof(X.FDateTime)}"); - Assert.AreEqual(all.Min(x => x.FTimeSpan), globalSession.Query.All().Select(x => x.FTimeSpan).Min(), $"Failed for {nameof(X.FTimeSpan)}"); + Assert.AreEqual(all.Min(x => x.FDateTime), GlobalSession.Query.All().Select(x => x.FDateTime).Min(), $"Failed for {nameof(X.FDateTime)}"); + Assert.AreEqual(all.Min(x => x.FTimeSpan), GlobalSession.Query.All().Select(x => x.FTimeSpan).Min(), $"Failed for {nameof(X.FTimeSpan)}"); } [Test] public void MinByValueItselfTest() { - Assert.AreEqual(all.Min(x => x.FByte), globalSession.Query.All().Select(x => x.FByte).Min(x => x), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Min(x => x.FSByte), globalSession.Query.All().Select(x => x.FSByte).Min(x => x), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Min(x => x.FByte), GlobalSession.Query.All().Select(x => x.FByte).Min(x => x), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Min(x => x.FSByte), GlobalSession.Query.All().Select(x => x.FSByte).Min(x => x), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Min(x => x.FShort), globalSession.Query.All().Select(x => x.FShort).Min(x => x), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Min(x => x.FUShort), globalSession.Query.All().Select(x => x.FUShort).Min(x => x), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Min(x => x.FShort), GlobalSession.Query.All().Select(x => x.FShort).Min(x => x), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Min(x => x.FUShort), GlobalSession.Query.All().Select(x => x.FUShort).Min(x => x), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Min(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Min(x => x), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Min(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Min(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Min(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Min(x => x), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Min(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Min(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Min(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Min(x => x), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Min(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Min(x => x), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Min(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Min(x => x), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Min(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Min(x => x), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Min(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Min(x => x), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Min(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Min(x => x), $"Failed for {nameof(X.FDecimal)}"); - Assert.AreEqual(all.Min(x => x.FDateTime), globalSession.Query.All().Select(x => x.FDateTime).Min(x => x), $"Failed for {nameof(X.FDateTime)}"); - Assert.AreEqual(all.Min(x => x.FTimeSpan), globalSession.Query.All().Select(x => x.FTimeSpan).Min(x => x), $"Failed for {nameof(X.FTimeSpan)}"); + Assert.AreEqual(all.Min(x => x.FDateTime), GlobalSession.Query.All().Select(x => x.FDateTime).Min(x => x), $"Failed for {nameof(X.FDateTime)}"); + Assert.AreEqual(all.Min(x => x.FTimeSpan), GlobalSession.Query.All().Select(x => x.FTimeSpan).Min(x => x), $"Failed for {nameof(X.FTimeSpan)}"); } [Test] public void MaxTest() { - Assert.AreEqual(all.Max(x => x.FByte), globalSession.Query.All().Max(x => x.FByte), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Max(x => x.FSByte), globalSession.Query.All().Max(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Max(x => x.FByte), GlobalSession.Query.All().Max(x => x.FByte), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Max(x => x.FSByte), GlobalSession.Query.All().Max(x => x.FSByte), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Max(x => x.FShort), globalSession.Query.All().Max(x => x.FShort), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Max(x => x.FUShort), globalSession.Query.All().Max(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Max(x => x.FShort), GlobalSession.Query.All().Max(x => x.FShort), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Max(x => x.FUShort), GlobalSession.Query.All().Max(x => x.FUShort), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Max(x => x.FInt), globalSession.Query.All().Max(x => x.FInt), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Max(x => x.FUInt), globalSession.Query.All().Max(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Max(x => x.FInt), GlobalSession.Query.All().Max(x => x.FInt), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Max(x => x.FUInt), GlobalSession.Query.All().Max(x => x.FUInt), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Max(x => x.FLong), globalSession.Query.All().Max(x => x.FLong), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Max(x => x.FFloat), globalSession.Query.All().Max(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Max(x => x.FDecimal), globalSession.Query.All().Max(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Max(x => x.FLong), GlobalSession.Query.All().Max(x => x.FLong), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Max(x => x.FFloat), GlobalSession.Query.All().Max(x => x.FFloat), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Max(x => x.FDecimal), GlobalSession.Query.All().Max(x => x.FDecimal), $"Failed for {nameof(X.FDecimal)}"); - Assert.AreEqual(all.Max(x => x.FDateTime), globalSession.Query.All().Max(x => x.FDateTime), $"Failed for {nameof(X.FDateTime)}"); - Assert.AreEqual(all.Max(x => x.FTimeSpan), globalSession.Query.All().Max(x => x.FTimeSpan), $"Failed for {nameof(X.FTimeSpan)}"); + Assert.AreEqual(all.Max(x => x.FDateTime), GlobalSession.Query.All().Max(x => x.FDateTime), $"Failed for {nameof(X.FDateTime)}"); + Assert.AreEqual(all.Max(x => x.FTimeSpan), GlobalSession.Query.All().Max(x => x.FTimeSpan), $"Failed for {nameof(X.FTimeSpan)}"); } [Test] public void MaxNoLambdaTest() { - Assert.AreEqual(all.Max(x => x.FByte), globalSession.Query.All().Select(x => x.FByte).Max(), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Max(x => x.FSByte), globalSession.Query.All().Select(x => x.FSByte).Max(), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Max(x => x.FByte), GlobalSession.Query.All().Select(x => x.FByte).Max(), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Max(x => x.FSByte), GlobalSession.Query.All().Select(x => x.FSByte).Max(), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Max(x => x.FShort), globalSession.Query.All().Select(x => x.FShort).Max(), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Max(x => x.FUShort), globalSession.Query.All().Select(x => x.FUShort).Max(), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Max(x => x.FShort), GlobalSession.Query.All().Select(x => x.FShort).Max(), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Max(x => x.FUShort), GlobalSession.Query.All().Select(x => x.FUShort).Max(), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Max(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Max(), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Max(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Max(), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Max(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Max(), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Max(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Max(), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Max(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Max(), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Max(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Max(), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Max(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Max(), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Max(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Max(), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Max(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Max(), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Max(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Max(), $"Failed for {nameof(X.FDecimal)}"); - Assert.AreEqual(all.Max(x => x.FDateTime), globalSession.Query.All().Select(x => x.FDateTime).Max(), $"Failed for {nameof(X.FDateTime)}"); - Assert.AreEqual(all.Max(x => x.FTimeSpan), globalSession.Query.All().Select(x => x.FTimeSpan).Max(), $"Failed for {nameof(X.FTimeSpan)}"); + Assert.AreEqual(all.Max(x => x.FDateTime), GlobalSession.Query.All().Select(x => x.FDateTime).Max(), $"Failed for {nameof(X.FDateTime)}"); + Assert.AreEqual(all.Max(x => x.FTimeSpan), GlobalSession.Query.All().Select(x => x.FTimeSpan).Max(), $"Failed for {nameof(X.FTimeSpan)}"); } [Test] public void MaxByValueItselfTest() { - Assert.AreEqual(all.Max(x => x.FByte), globalSession.Query.All().Select(x => x.FByte).Max(x => x), $"Failed for {nameof(X.FByte)}"); - Assert.AreEqual(all.Max(x => x.FSByte), globalSession.Query.All().Select(x => x.FSByte).Max(x => x), $"Failed for {nameof(X.FSByte)}"); + Assert.AreEqual(all.Max(x => x.FByte), GlobalSession.Query.All().Select(x => x.FByte).Max(x => x), $"Failed for {nameof(X.FByte)}"); + Assert.AreEqual(all.Max(x => x.FSByte), GlobalSession.Query.All().Select(x => x.FSByte).Max(x => x), $"Failed for {nameof(X.FSByte)}"); - Assert.AreEqual(all.Max(x => x.FShort), globalSession.Query.All().Select(x => x.FShort).Max(x => x), $"Failed for {nameof(X.FShort)}"); - Assert.AreEqual(all.Max(x => x.FUShort), globalSession.Query.All().Select(x => x.FUShort).Max(x => x), $"Failed for {nameof(X.FUShort)}"); + Assert.AreEqual(all.Max(x => x.FShort), GlobalSession.Query.All().Select(x => x.FShort).Max(x => x), $"Failed for {nameof(X.FShort)}"); + Assert.AreEqual(all.Max(x => x.FUShort), GlobalSession.Query.All().Select(x => x.FUShort).Max(x => x), $"Failed for {nameof(X.FUShort)}"); - Assert.AreEqual(all.Max(x => x.FInt), globalSession.Query.All().Select(x => x.FInt).Max(x => x), $"Failed for {nameof(X.FInt)}"); - Assert.AreEqual(all.Max(x => x.FUInt), globalSession.Query.All().Select(x => x.FUInt).Max(x => x), $"Failed for {nameof(X.FUInt)}"); + Assert.AreEqual(all.Max(x => x.FInt), GlobalSession.Query.All().Select(x => x.FInt).Max(x => x), $"Failed for {nameof(X.FInt)}"); + Assert.AreEqual(all.Max(x => x.FUInt), GlobalSession.Query.All().Select(x => x.FUInt).Max(x => x), $"Failed for {nameof(X.FUInt)}"); - Assert.AreEqual(all.Max(x => x.FLong), globalSession.Query.All().Select(x => x.FLong).Max(x => x), $"Failed for {nameof(X.FLong)}"); - Assert.AreEqual(all.Max(x => x.FFloat), globalSession.Query.All().Select(x => x.FFloat).Max(x => x), $"Failed for {nameof(X.FFloat)}"); - Assert.AreEqual(all.Max(x => x.FDecimal), globalSession.Query.All().Select(x => x.FDecimal).Max(x => x), $"Failed for {nameof(X.FDecimal)}"); + Assert.AreEqual(all.Max(x => x.FLong), GlobalSession.Query.All().Select(x => x.FLong).Max(x => x), $"Failed for {nameof(X.FLong)}"); + Assert.AreEqual(all.Max(x => x.FFloat), GlobalSession.Query.All().Select(x => x.FFloat).Max(x => x), $"Failed for {nameof(X.FFloat)}"); + Assert.AreEqual(all.Max(x => x.FDecimal), GlobalSession.Query.All().Select(x => x.FDecimal).Max(x => x), $"Failed for {nameof(X.FDecimal)}"); - Assert.AreEqual(all.Max(x => x.FDateTime), globalSession.Query.All().Select(x => x.FDateTime).Max(x => x), $"Failed for {nameof(X.FDateTime)}"); - Assert.AreEqual(all.Max(x => x.FTimeSpan), globalSession.Query.All().Select(x => x.FTimeSpan).Max(x => x), $"Failed for {nameof(X.FTimeSpan)}"); + Assert.AreEqual(all.Max(x => x.FDateTime), GlobalSession.Query.All().Select(x => x.FDateTime).Max(x => x), $"Failed for {nameof(X.FDateTime)}"); + Assert.AreEqual(all.Max(x => x.FTimeSpan), GlobalSession.Query.All().Select(x => x.FTimeSpan).Max(x => x), $"Failed for {nameof(X.FTimeSpan)}"); } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs index 9718e9fe05..2f9d00de55 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2023 Xtensive LLC. +// Copyright (C) 2019-2025 Xtensive LLC. // This code is distributed under MIT license terms. // See the License.txt file in the project root for more information. // Created by: Alexey Kulakov diff --git a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/NullValuesTest.cs b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/NullValuesTest.cs index a7c8c7fd7b..16b8489373 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/NullValuesTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/NullValuesTest.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2023 Xtensive LLC. +// Copyright (C) 2009-2025 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 @@ -18,22 +18,23 @@ public class NullValuesTest : AutoBuildTest { private bool emptyStringIsNull; + protected override bool InitGlobalSession => true; + public override void TestFixtureSetUp() { base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); emptyStringIsNull = ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull); - new X {FString = "Xtensive"}; - new X {FString = null}; - new X {FString = string.Empty}; + _ = new X(GlobalSession) {FString = "Xtensive"}; + _ = new X(GlobalSession) {FString = null}; + _ = new X(GlobalSession) {FString = string.Empty}; } [Test] public void CompareWithEmptyStringParameterTest() { var value = string.Empty; - var result = Session.Demand().Query.All().Where(x => x.FString==value).ToList(); + var result = GlobalSession.Query.All().Where(x => x.FString==value).ToList(); if (emptyStringIsNull) CheckIsNull(result, 2); else @@ -44,7 +45,7 @@ public void CompareWithEmptyStringParameterTest() public void CompareWithNullStringParameterTest() { string value = null; - var result = Session.Demand().Query.All().Where(x => x.FString==value).ToList(); + var result = GlobalSession.Query.All().Where(x => x.FString==value).ToList(); CheckIsNull(result, emptyStringIsNull ? 2 : 1); } @@ -52,7 +53,7 @@ public void CompareWithNullStringParameterTest() public void CompareWithEmptyStringConstantTest() { // NOTE: string.Empty should not be used here, because it is translated via string parameter - var result = Session.Demand().Query.All().Where(x => x.FString=="").ToList(); + var result = GlobalSession.Query.All().Where(x => x.FString=="").ToList(); if (emptyStringIsNull) CheckIsNull(result, 2); else @@ -62,7 +63,7 @@ public void CompareWithEmptyStringConstantTest() [Test] public void CompareWithNullStringConstantTest() { - var result = Session.Demand().Query.All().Where(x => x.FString==null).ToList(); + var result = GlobalSession.Query.All().Where(x => x.FString==null).ToList(); CheckIsNull(result, emptyStringIsNull ? 2 : 1); } @@ -70,7 +71,7 @@ public void CompareWithNullStringConstantTest() public void SelectNullStringParameter() { string value = null; - var result = Session.Demand().Query.All().Select(x => new {x.Id, Value = value}).ToList(); + var result = GlobalSession.Query.All().Select(x => new {x.Id, Value = value}).ToList(); foreach (var item in result) Assert.IsNull(item.Value); } diff --git a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/RoundingTest.cs b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/RoundingTest.cs index fdac9a83a1..e0034dd893 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/RoundingTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/RoundingTest.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2023 Xtensive LLC. +// Copyright (C) 2009-2025 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 @@ -19,14 +19,16 @@ public class RoundingTest : AutoBuildTest private const double DoubleDelta = 0.00000001d; private const decimal DecimalDelta = 0.000000000001m; + protected override bool InitGlobalSession => true; + [Test] public void TruncateTest() { - Query.All().Select(x => new { Decimal = x.d18_9, DecimalTruncate = Math.Truncate(x.d18_9) }) + GlobalSession.Query.All().Select(x => new { Decimal = x.d18_9, DecimalTruncate = Math.Truncate(x.d18_9) }) .GroupBy(x => x.DecimalTruncate) .ForEach(i => i.ForEach(x => AreEqual(Math.Truncate(x.Decimal), x.DecimalTruncate))); - Query.All().Select(x => new { Double = x.FDouble, DoubleTruncate = Math.Truncate(x.FDouble) }) + GlobalSession.Query.All().Select(x => new { Double = x.FDouble, DoubleTruncate = Math.Truncate(x.FDouble) }) .GroupBy(x => x.DoubleTruncate) .ForEach(i => i.ForEach(x => AreEqual(Math.Truncate(x.Double), x.DoubleTruncate))); } @@ -34,12 +36,12 @@ public void TruncateTest() [Test] public void CeilTest() { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalCeiling = Math.Ceiling(x.d18_9) }) .GroupBy(x => x.DecimalCeiling) .ForEach(x => x.ForEach(i => AreEqual(Math.Ceiling(i.Decimal), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleCeiling = Math.Ceiling(x.FDouble) }) .GroupBy(x => x.DoubleCeiling) .ForEach(x => x.ForEach(i => AreEqual(Math.Ceiling(i.Double), x.Key))); @@ -48,12 +50,12 @@ public void CeilTest() [Test] public void FloorTest() { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalFloor = Math.Floor(x.d18_9) }) .GroupBy(x => x.DecimalFloor) .ForEach(x => x.ForEach(i => AreEqual(Math.Floor(i.Decimal), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleFloor = Math.Floor(x.FDouble) }) .GroupBy(x => x.DoubleFloor) .ForEach(x => x.ForEach(i => AreEqual(Math.Floor(i.Double), x.Key))); @@ -62,12 +64,12 @@ public void FloorTest() [Test] public void RoundDefaultToZeroDigitsTest() { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9) }) .GroupBy(x => x.DecimalRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Decimal), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble) }) .GroupBy(x => x.DoubleRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Double), x.Key))); @@ -78,24 +80,24 @@ public void RoundDefaultToNonZeroDigitsTest() { if (ExpectNotSupported()) { var ex = Assert.Throws(() => - Query.All().Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1) }) + GlobalSession.Query.All().Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1) }) .GroupBy(x => x.DecimalRound).Run()); Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message.Contains("Power", StringComparison.Ordinal)); ex = Assert.Throws(() => - Query.All().Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1) }) + GlobalSession.Query.All().Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1) }) .GroupBy(x => x.DoubleRound).Run()); Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message.Contains("Power", StringComparison.Ordinal)); } else { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1) }) .GroupBy(x => x.DecimalRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Decimal, 1), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1) }) .GroupBy(x => x.DoubleRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Double, 1), x.Key))); @@ -107,12 +109,12 @@ public void RoundDefaultToNonZeroDigitsTest() [Test] public void RoundToEvenToZeroDigitsTest() { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, MidpointRounding.ToEven) }) .GroupBy(x => x.DecimalRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Decimal, MidpointRounding.ToEven), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, MidpointRounding.ToEven) }) .GroupBy(x => x.DoubleRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Double, MidpointRounding.ToEven), x.Key))); @@ -123,24 +125,24 @@ public void RoundToEvenToNonZeroDigitsTest() { if (ExpectNotSupported()) {// sqlite has no support for Power operation var ex = Assert.Throws(() => - Query.All().Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1, MidpointRounding.ToEven) }) + GlobalSession.Query.All().Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1, MidpointRounding.ToEven) }) .GroupBy(x => x.DecimalRound).Run()); Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message.Contains("Power", StringComparison.Ordinal)); ex = Assert.Throws(() => - Query.All().Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1, MidpointRounding.ToEven) }) + GlobalSession.Query.All().Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1, MidpointRounding.ToEven) }) .GroupBy(x => x.DoubleRound).Run()); Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message.Contains("Power", StringComparison.Ordinal)); } else { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1, MidpointRounding.ToEven) }) .GroupBy(x => x.DecimalRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Decimal, 1, MidpointRounding.ToEven), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1, MidpointRounding.ToEven) }) .GroupBy(x => x.DoubleRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Double, 1, MidpointRounding.ToEven), x.Key))); @@ -150,12 +152,12 @@ public void RoundToEvenToNonZeroDigitsTest() [Test] public void RoundAwayFromZeroToZeroDigitsTest() { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, MidpointRounding.AwayFromZero) }) .GroupBy(x => x.DecimalRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Decimal, MidpointRounding.AwayFromZero), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, MidpointRounding.AwayFromZero) }) .GroupBy(x => x.DoubleRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Double, MidpointRounding.AwayFromZero), x.Key))); @@ -166,24 +168,24 @@ public void RoundAwayFromZeroToNonZeroDigitsTest() { if (ExpectNotSupported()) { var ex = Assert.Throws(() => - Query.All().Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1, MidpointRounding.AwayFromZero) }) + GlobalSession.Query.All().Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1, MidpointRounding.AwayFromZero) }) .GroupBy(x => x.DecimalRound).Run()); Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message.Contains("Power", StringComparison.Ordinal)); ex = Assert.Throws(() => - Query.All().Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1, MidpointRounding.AwayFromZero) }) + GlobalSession.Query.All().Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1, MidpointRounding.AwayFromZero) }) .GroupBy(x => x.DoubleRound).Run()); Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message.Contains("Power", StringComparison.Ordinal)); } else { - Query.All() + GlobalSession.Query.All() .Select(x => new { Decimal = x.d18_9, DecimalRound = Math.Round(x.d18_9, 1, MidpointRounding.AwayFromZero) }) .GroupBy(x => x.DecimalRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Decimal, 1, MidpointRounding.AwayFromZero), x.Key))); - Query.All() + GlobalSession.Query.All() .Select(x => new { Double = x.FDouble, DoubleRound = Math.Round(x.FDouble, 1, MidpointRounding.AwayFromZero) }) .GroupBy(x => x.DoubleRound) .ForEach(x => x.ForEach(i => AreEqual(Math.Round(i.Double, 1, MidpointRounding.AwayFromZero), x.Key))); @@ -193,7 +195,6 @@ public void RoundAwayFromZeroToNonZeroDigitsTest() public override void TestFixtureSetUp() { base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); var testValues = new[] { 1.3m, 1.5m, 1.6m, @@ -230,8 +231,8 @@ public override void TestFixtureSetUp() }; foreach (var value in testValues) { - _ = new DoubleContainer { FDouble = (double) value }; - _ = new DecimalContainer { d18_9 = value }; + _ = new DoubleContainer (GlobalSession) { FDouble = (double) value }; + _ = new DecimalContainer (GlobalSession) { d18_9 = value }; //_ = new X { FDouble = (double) value, FDecimal = value }; } } diff --git a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs index 633321395f..5c91602c34 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2023 Xtensive LLC. +// Copyright (C) 2009-2025 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 diff --git a/Orm/Xtensive.Orm.Tests/Storage/TypeCompatibilityTest.cs b/Orm/Xtensive.Orm.Tests/Storage/TypeCompatibilityTest.cs index 6eafe43715..cb3c26d26a 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/TypeCompatibilityTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/TypeCompatibilityTest.cs @@ -241,6 +241,15 @@ public class X : Entity [Field] public EULong? FNEULong { get; set; } + public X(Session session) + : base(session) + { + } + + public X() + : base() + { + } } [HierarchyRoot] @@ -254,6 +263,11 @@ public class DecimalContainer : Entity [Field(Precision = 18, Scale = 0)] public decimal d18_0 { get; set; } + + public DecimalContainer(Session session) + : base(session) + { + } } [HierarchyRoot] @@ -264,6 +278,11 @@ public class DoubleContainer : Entity [Field] public double FDouble { get; set; } + + public DoubleContainer(Session session) + : base(session) + { + } } } @@ -388,7 +407,7 @@ public void DecimalTest() using (var session = Domain.OpenSession()) { Key key; using (var transactionScope = session.OpenTransaction()) { - var container = new DecimalContainer() { + var container = new DecimalContainer(session) { d18_9 = d18_9, d18_0 = d18_0 }; From d1ac731d88167f9da7dede3e25132889f903fd77 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Tue, 14 Jan 2025 19:35:38 +0500 Subject: [PATCH 07/23] More tests use global session --- .../Linq/WhereByEnumTest.cs | 224 ++++++++---------- .../CommandProcessorContextProviderTest.cs | 9 +- .../Providers/Sql/StringOperationsTest.cs | 19 +- 3 files changed, 116 insertions(+), 136 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs b/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs index 03c725d8f3..82e03062ab 100644 --- a/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs +++ b/Orm/Xtensive.Orm.Tests/Linq/WhereByEnumTest.cs @@ -165,21 +165,23 @@ namespace Xtensive.Orm.Tests.Linq { public class WhereByEnumTest : AutoBuildTest { - private Session sharedSession; private string castSign; + private QueryFormatter queryFormatter; + + protected override bool InitGlobalSession => true; public override void TestFixtureSetUp() { base.TestFixtureSetUp(); - sharedSession = CreateSessionAndTransaction().Item1; castSign = StorageProviderInfo.Instance.CheckProviderIs(StorageProvider.PostgreSql) ? "::" : "CAST"; + queryFormatter = GlobalSession.Services.Demand(); } public override void TestFixtureTearDown() { - sharedSession = null; + queryFormatter = null; base.TestFixtureTearDown(); } @@ -193,78 +195,72 @@ protected override DomainConfiguration BuildConfiguration() protected override void PopulateData() { - using (var session = Domain.OpenSession()) - using (var tx = session.OpenTransaction()) { - _ = new EnumContainer(session, EnumContainer.Zero); - _ = new EnumContainer(session, EnumContainer.One); - _ = new EnumContainer(session, EnumContainer.Two); - _ = new EnumContainer(session, EnumContainer.Max); - tx.Complete(); - } + _ = new EnumContainer(GlobalSession, EnumContainer.Zero); + _ = new EnumContainer(GlobalSession, EnumContainer.One); + _ = new EnumContainer(GlobalSession, EnumContainer.Two); + _ = new EnumContainer(GlobalSession, EnumContainer.Max); } [Test] public void ByteTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.ByteEnumField != ByteEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.ByteEnumField != ByteEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ByteEnumField > ByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.ByteEnumField > ByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.ByteEnumField >= ByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.ByteEnumField >= ByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ByteEnumField < ByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ByteEnumField < ByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.ByteEnumField <= ByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ByteEnumField <= ByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ByteEnumField == ByteEnum.Max); + query = GlobalSession.Query.All().Where(e => e.ByteEnumField == ByteEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NByteEnumField != ByteEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NByteEnumField != ByteEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NByteEnumField > ByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.NByteEnumField > ByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NByteEnumField >= ByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.NByteEnumField >= ByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NByteEnumField < ByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NByteEnumField < ByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NByteEnumField <= ByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NByteEnumField <= ByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NByteEnumField == ByteEnum.Max); + query = GlobalSession.Query.All().Where(e => e.NByteEnumField == ByteEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -273,65 +269,63 @@ public void ByteTest() [Test] public void SByteTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.SByteEnumField != SByteEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.SByteEnumField != SByteEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.SByteEnumField > SByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.SByteEnumField > SByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.SByteEnumField >= SByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.SByteEnumField >= SByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.SByteEnumField < SByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.SByteEnumField < SByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.SByteEnumField <= SByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.SByteEnumField <= SByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.SByteEnumField == SByteEnum.Max); + query = GlobalSession.Query.All().Where(e => e.SByteEnumField == SByteEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NSByteEnumField != SByteEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NSByteEnumField != SByteEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NSByteEnumField > SByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.NSByteEnumField > SByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NSByteEnumField >= SByteEnum.One); + query = GlobalSession.Query.All().Where(e => e.NSByteEnumField >= SByteEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NSByteEnumField < SByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NSByteEnumField < SByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NSByteEnumField <= SByteEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NSByteEnumField <= SByteEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NSByteEnumField == SByteEnum.Max); + query = GlobalSession.Query.All().Where(e => e.NSByteEnumField == SByteEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -340,55 +334,53 @@ public void SByteTest() [Test] public void ShortTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Max); + query = GlobalSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NShortEnumField != ShortEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NShortEnumField != ShortEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NShortEnumField > ShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.NShortEnumField > ShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NShortEnumField >= ShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.NShortEnumField >= ShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ShortEnumField < ShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ShortEnumField < ShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.ShortEnumField <= ShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ShortEnumField <= ShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Max); + query = GlobalSession.Query.All().Where(e => e.ShortEnumField == ShortEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -397,65 +389,63 @@ public void ShortTest() [Test] public void UShortTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.UShortEnumField != UShortEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.UShortEnumField != UShortEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UShortEnumField > UShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.UShortEnumField > UShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.UShortEnumField >= UShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.UShortEnumField >= UShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UShortEnumField < UShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.UShortEnumField < UShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.UShortEnumField <= UShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.UShortEnumField <= UShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UShortEnumField == UShortEnum.Max); + query = GlobalSession.Query.All().Where(e => e.UShortEnumField == UShortEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NUShortEnumField != UShortEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NUShortEnumField != UShortEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NUShortEnumField > UShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.NUShortEnumField > UShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NUShortEnumField >= UShortEnum.One); + query = GlobalSession.Query.All().Where(e => e.NUShortEnumField >= UShortEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NUShortEnumField < UShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NUShortEnumField < UShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NUShortEnumField <= UShortEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NUShortEnumField <= UShortEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UShortEnumField == UShortEnum.Max); + query = GlobalSession.Query.All().Where(e => e.UShortEnumField == UShortEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -464,65 +454,63 @@ public void UShortTest() [Test] public void IntTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.IntEnumField != IntEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.IntEnumField != IntEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.IntEnumField > IntEnum.One); + query = GlobalSession.Query.All().Where(e => e.IntEnumField > IntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.IntEnumField >= IntEnum.One); + query = GlobalSession.Query.All().Where(e => e.IntEnumField >= IntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.IntEnumField < IntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.IntEnumField < IntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.IntEnumField <= IntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.IntEnumField <= IntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.IntEnumField == IntEnum.Max); + query = GlobalSession.Query.All().Where(e => e.IntEnumField == IntEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NIntEnumField != IntEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NIntEnumField != IntEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NIntEnumField > IntEnum.One); + query = GlobalSession.Query.All().Where(e => e.NIntEnumField > IntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NIntEnumField >= IntEnum.One); + query = GlobalSession.Query.All().Where(e => e.NIntEnumField >= IntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NIntEnumField < IntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NIntEnumField < IntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NIntEnumField <= IntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NIntEnumField <= IntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NIntEnumField == IntEnum.Max); + query = GlobalSession.Query.All().Where(e => e.NIntEnumField == IntEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -531,65 +519,63 @@ public void IntTest() [Test] public void UIntTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.UIntEnumField != UIntEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.UIntEnumField != UIntEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UIntEnumField > UIntEnum.One); + query = GlobalSession.Query.All().Where(e => e.UIntEnumField > UIntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.UIntEnumField >= UIntEnum.One); + query = GlobalSession.Query.All().Where(e => e.UIntEnumField >= UIntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UIntEnumField < UIntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.UIntEnumField < UIntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.UIntEnumField <= UIntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.UIntEnumField <= UIntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.UIntEnumField == UIntEnum.Max); + query = GlobalSession.Query.All().Where(e => e.UIntEnumField == UIntEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NUIntEnumField != UIntEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NUIntEnumField != UIntEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NUIntEnumField > UIntEnum.One); + query = GlobalSession.Query.All().Where(e => e.NUIntEnumField > UIntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NUIntEnumField >= UIntEnum.One); + query = GlobalSession.Query.All().Where(e => e.NUIntEnumField >= UIntEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NUIntEnumField < UIntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NUIntEnumField < UIntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NUIntEnumField <= UIntEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NUIntEnumField <= UIntEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NUIntEnumField == UIntEnum.Max); + query = GlobalSession.Query.All().Where(e => e.NUIntEnumField == UIntEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -598,69 +584,67 @@ public void UIntTest() [Test] public void LongTest() { - var queryFormatter = sharedSession.Services.Demand(); - var substractValue = StorageProviderInfo.Instance.CheckProviderIs(StorageProvider.SqlServer) ? castSign.Length : 0; - var query = sharedSession.Query.All().Where(e => e.LongEnumField != LongEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.LongEnumField != LongEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.LongEnumField > LongEnum.One); + query = GlobalSession.Query.All().Where(e => e.LongEnumField > LongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.LongEnumField >= LongEnum.One); + query = GlobalSession.Query.All().Where(e => e.LongEnumField >= LongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.LongEnumField < LongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.LongEnumField < LongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.LongEnumField <= LongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.LongEnumField <= LongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.LongEnumField == LongEnum.Max); + query = GlobalSession.Query.All().Where(e => e.LongEnumField == LongEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NLongEnumField != LongEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NLongEnumField != LongEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NLongEnumField > LongEnum.One); + query = GlobalSession.Query.All().Where(e => e.NLongEnumField > LongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NLongEnumField >= LongEnum.One); + query = GlobalSession.Query.All().Where(e => e.NLongEnumField >= LongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NLongEnumField < LongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NLongEnumField < LongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NLongEnumField <= LongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NLongEnumField <= LongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NLongEnumField == LongEnum.Max); + query = GlobalSession.Query.All().Where(e => e.NLongEnumField == LongEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length - substractValue)); Assert.That(query.Count(), Is.EqualTo(1)); @@ -669,65 +653,63 @@ public void LongTest() [Test] public void ULongTest() { - var queryFormatter = sharedSession.Services.Demand(); - - var query = sharedSession.Query.All().Where(e => e.ULongEnumField != ULongEnum.Zero); + var query = GlobalSession.Query.All().Where(e => e.ULongEnumField != ULongEnum.Zero); var queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ULongEnumField > ULongEnum.One); + query = GlobalSession.Query.All().Where(e => e.ULongEnumField > ULongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.ULongEnumField >= ULongEnum.One); + query = GlobalSession.Query.All().Where(e => e.ULongEnumField >= ULongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ULongEnumField < ULongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ULongEnumField < ULongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.ULongEnumField <= ULongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.ULongEnumField <= ULongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.ULongEnumField == ULongEnum.Max); + query = GlobalSession.Query.All().Where(e => e.ULongEnumField == ULongEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); - query = sharedSession.Query.All().Where(e => e.NULongEnumField != ULongEnum.Zero); + query = GlobalSession.Query.All().Where(e => e.NULongEnumField != ULongEnum.Zero); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NULongEnumField > ULongEnum.One); + query = GlobalSession.Query.All().Where(e => e.NULongEnumField > ULongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NULongEnumField >= ULongEnum.One); + query = GlobalSession.Query.All().Where(e => e.NULongEnumField >= ULongEnum.One); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NULongEnumField < ULongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NULongEnumField < ULongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(2)); - query = sharedSession.Query.All().Where(e => e.NULongEnumField <= ULongEnum.Two); + query = GlobalSession.Query.All().Where(e => e.NULongEnumField <= ULongEnum.Two); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(3)); - query = sharedSession.Query.All().Where(e => e.NULongEnumField == ULongEnum.Max); + query = GlobalSession.Query.All().Where(e => e.NULongEnumField == ULongEnum.Max); queryString = queryFormatter.ToSqlString(query); Assert.That(queryString.Replace(castSign, "").Length, Is.EqualTo(queryString.Length)); Assert.That(query.Count(), Is.EqualTo(1)); diff --git a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs index 2f9d00de55..12e9f80ff2 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessorContextProviderTest.cs @@ -10,15 +10,12 @@ namespace Xtensive.Orm.Tests.Storage { public class CommandProcessorContextProviderTest : AutoBuildTest { - protected override void PopulateData() - { - _ = CreateSessionAndTransaction(); - } + protected override bool InitGlobalSession => true; [Test] public void GetContextTest() { - var session = Session.Demand(); + var session = GlobalSession; var provider = session.CommandProcessorContextProvider; var context = provider.ProvideContext(); @@ -36,7 +33,7 @@ public void GetContextTest() [Test] public void GetContextForPartialExecutionTest() { - var session = Session.Demand(); + var session = GlobalSession; var provider = session.CommandProcessorContextProvider; var context = provider.ProvideContext(true); diff --git a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs index 5c91602c34..b589c4506f 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/Providers/Sql/StringOperationsTest.cs @@ -19,6 +19,8 @@ public class StringOperationsTest : AutoBuildTest private bool emptyStringIsNull; + protected override bool InitGlobalSession => true; + protected override DomainConfiguration BuildConfiguration() { var configuration = base.BuildConfiguration(); @@ -29,7 +31,6 @@ protected override DomainConfiguration BuildConfiguration() public override void TestFixtureSetUp() { base.TestFixtureSetUp(); - _ = CreateSessionAndTransaction(); emptyStringIsNull = ProviderInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull); var testValues = new[] { // test values for TrimStart, TrimEnd, Trim @@ -76,7 +77,7 @@ public override void TestFixtureSetUp() [Test] public void LengthTest() { - var results = Session.Demand().Query.All().Select(x => new { + var results = GlobalSession.Query.All().Select(x => new { String = x.FString, Length = x.FString.Length }).ToList(); @@ -89,7 +90,7 @@ public void LengthTest() [Test] public void TrimSpaceTest() { - var results = Session.Demand().Query.All() + var results = GlobalSession.Query.All() .Select(x => new { String = x.FString, StringTrim = x.FString.Trim(), @@ -119,7 +120,7 @@ public void TrimSpaceTest() public void TrimOtherCharTest() { Require.ProviderIsNot(StorageProvider.SqlServer | StorageProvider.SqlServerCe); - var results = Session.Demand().Query.All() + var results = GlobalSession.Query.All() .Select(x => new { String = x.FString, StringTrimLeadingLargePLetter = x.FString.TrimStart('P'), @@ -137,7 +138,7 @@ public void TrimOtherCharTest() public void TrimMultipleCharsTest() { Require.ProviderIsNot(StorageProvider.SqlServer | StorageProvider.Oracle | StorageProvider.SqlServerCe); - var results = Session.Demand().Query.All() + var results = GlobalSession.Query.All() .Select(x => new { String = x.FString, StringTrimLeadingZeroAndOne = x.FString.TrimStart('0', '1'), @@ -154,7 +155,7 @@ public void TrimMultipleCharsTest() [Test] public void StartsWithTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = GlobalSession.Query.All().Select(x => new { x.Id, String = x.FString, StartsWithA = x.FString.StartsWith("A"), @@ -181,7 +182,7 @@ public void StartsWithTest() [Test] public void EndsWithTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = GlobalSession.Query.All().Select(x => new { x.Id, String = x.FString, EndsWithA = x.FString.EndsWith("A"), @@ -208,7 +209,7 @@ public void EndsWithTest() [Test] public void ContainsTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = GlobalSession.Query.All().Select(x => new { x.Id, String = x.FString, ContainsA = x.FString.Contains("A"), @@ -239,7 +240,7 @@ public void ContainsTest() [Test] public void PaddingTest() { - var result = Session.Demand().Query.All().Select(x => new { + var result = GlobalSession.Query.All().Select(x => new { x.Id, String = x.FString, PadLeft = x.FString.PadLeft(10), From 94a6020e673251afaea579ab26289b8b0d5e1e51 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 15 Jan 2025 13:29:36 +0500 Subject: [PATCH 08/23] AutoBuildTest: Fixed error message on attempt to access uninitialized global session --- Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs b/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs index 8464df455e..01069e6bc6 100644 --- a/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs +++ b/Orm/Xtensive.Orm.Tests.Framework/AutoBuildTest.cs @@ -18,6 +18,8 @@ namespace Xtensive.Orm.Tests public abstract class AutoBuildTest : HasConfigurationAccessTest { private const string ErrorInTestFixtureSetup = "Error in TestFixtureSetUp:\r\n{0}"; + private const string ErrorNotInitializedGlobalSession = "Set InitGlobalSession to true"; + private DisposableSet disposables; private (Session session, TransactionScope transaction) globalSessionAndTransaction; @@ -33,8 +35,8 @@ public abstract class AutoBuildTest : HasConfigurationAccessTest // Use these two for read-only tests only, don't change them, they are controlled by AutoBuildTest. // If there is need to change Session/Transactionscope or add/modify/remove entities // then open dedicated Session/TransactionScope within test - protected Session GlobalSession => InitGlobalSession ? globalSessionAndTransaction.session : throw new Exception("Set UseGlobalSession to true"); - protected TransactionScope GlobalTransaction => InitGlobalSession ? globalSessionAndTransaction.transaction : throw new Exception("Set UseGlobalSession to true"); + protected Session GlobalSession => InitGlobalSession ? globalSessionAndTransaction.session : throw new Exception(ErrorNotInitializedGlobalSession); + protected TransactionScope GlobalTransaction => InitGlobalSession ? globalSessionAndTransaction.transaction : throw new Exception(ErrorNotInitializedGlobalSession); [OneTimeSetUp] public virtual void TestFixtureSetUp() From 0c71b40f2b24f8ab7e69f7e447c13f059e60ee7c Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 15 Jan 2025 17:58:26 +0500 Subject: [PATCH 09/23] Move test to correct namespace --- .../Issues/IssueJira0117_FKStructureTest.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0117_FKStructureTest.cs b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0117_FKStructureTest.cs index 7e60143b29..9692e7a4af 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0117_FKStructureTest.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0117_FKStructureTest.cs @@ -1,6 +1,6 @@ -// Copyright (C) 2011 Xtensive LLC. -// All rights reserved. -// For conditions of distribution and use, see license. +// Copyright (C) 2011-2025 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 // Created: 2011.05.19 @@ -8,11 +8,11 @@ using System.Linq; using NUnit.Framework; using Xtensive.Orm.Configuration; -using Xtensive.Orm.Tests.Storage.MultipleFKViaStructureTestModel; +using Xtensive.Orm.Tests.Issues.MultipleFKViaStructureTestModel; using Xtensive.Orm.Providers; using Xtensive.Sql.Model; -namespace Xtensive.Orm.Tests.Storage.MultipleFKViaStructureTestModel +namespace Xtensive.Orm.Tests.Issues.MultipleFKViaStructureTestModel { [HierarchyRoot] public class Target1 : Entity @@ -81,7 +81,7 @@ public class Owner3 : Entity } } -namespace Xtensive.Orm.Tests.Storage +namespace Xtensive.Orm.Tests.Issues { public class IssueJira0117_FKStructureTest : AutoBuildTest { From 84f7596dbda088f9026e7da9594671e51966405d Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 20 Jan 2025 16:00:16 +0500 Subject: [PATCH 10/23] Add tests that checks Validator results --- .../Model/HierarchyRootValidationTest.cs | 3346 +++++++++++++++++ 1 file changed, 3346 insertions(+) create mode 100644 Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs diff --git a/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs b/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs new file mode 100644 index 0000000000..aecea0931c --- /dev/null +++ b/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs @@ -0,0 +1,3346 @@ +// Copyright (C) 2025 Xtensive LLC. +// This code is distributed under MIT license terms. +// See the License.txt file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using NUnit.Framework; +using Xtensive.Core; +using Xtensive.IoC; +using Xtensive.Orm.Building; +using Xtensive.Orm.Building.Builders; +using Xtensive.Orm.Building.Definitions; +using Xtensive.Orm.Configuration; +using Xtensive.Orm.Model; +using Xtensive.Tuples; +using Models = Xtensive.Orm.Tests.Model.HierarchyRootValidationTestModel; + +namespace Xtensive.Orm.Tests.Model +{ + [TestFixture] + public sealed class HierarchyRootValidationTest + { + private const string CantBeOfMsg = "can't be of"; + private const string UnableToCreateKeyForMsg = "Unable to create key for"; + private const string UnsupportedTypeMsg = "Unsupported type"; + private const string KeyGeneratorCanServeHierarchyWithOneKeyFieldMsg = "generator can serve hierarchy with exactly one key field"; + + [Test] + public void ValidNonPersistentKeyTypesForDefaultGeneratorTest() + { + Domain domain = null; + + var configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.ByteKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.ByteKeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.Int16KeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.Int16KeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.UInt16KeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.UInt16KeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.Int32KeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.Int32KeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.UInt32KeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.UInt32KeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.Int64KeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.Int64KeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.UInt64KeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.UInt64KeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.LimitedStringKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.LimitedStringKeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.StringKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.StringKeyEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.GuidKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.GuidKeyEntity(session); + session.SaveChanges(); + }); + } + } + + [Test] + public void InvalidNonPersistentKeyTypesForDefaultGeneratorTest() + { + // NOTE!!! + // To make user's life easier on writing model classes DO implicitly changes + // key generator kind to KeyGeneratorKind.None for the hierarchies which key fields + // don't match certain conditions. + // Such "correction" makes Domain seem functional but exceptions can happen + // while working with domain. + + // This benifits in short term but in long term creates another "caviar" for user to remember + // along his project live, newcomers will probably not know this which can cause instability. + + Domain domain = null; + var configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.FloatKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.FloatKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.FloatKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DoubleKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DoubleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.DoubleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DecimalKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DecimalKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.DecimalKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.FractionalDecimalKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.FractionalDecimalKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.FractionalDecimalKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.TimeSpanKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.TimeSpanKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.TimeSpanKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + +#if NET6_0_OR_GREATER + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.TimeOnlyKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.TimeOnlyKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.TimeOnlyKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DateOnlyKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DateOnlyKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.DateOnlyKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } +#endif + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DateTimeKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DateTimeKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.DateTimeKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + if (StorageProviderInfo.Instance.CheckProviderIs(StorageProvider.SqlServer)) { + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DateTimeOffsetKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.DateTimeOffsetKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.DateTimeOffsetKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.CharKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.NonPersistentStorageSupporedTypesAsKeys.CharKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentStorageSupporedTypesAsKeys.CharKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + } + + [Test] + public void NonPersistentComplexKeyTest() + { + // NOTE!!! + // To make user's life easier on writing model classes DO implicitly changes + // key generator kind to KeyGeneratorKind.None for the hierarchies which key fields + // don't match certain conditions. + // Such "correction" makes Domain seem functional but exceptions can happen + // while working with domain. + + // This benifits in short term but in long term creates another "caviar" for user to remember + // along his project live, newcomers will probably not know this which can cause instability. + + Domain domain = null; + var configuration = CreateDomainConfiguration(new[] { typeof(Models.NonPersistentComplexKey.ByteKeyEntity) }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.NonPersistentComplexKey.ByteKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.NonPersistentComplexKey.ByteKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + } + + [Test] + public void PersistentInterfaceKeyTest() + { + // NOTE!!! + // To make user's life easier on writing model classes DO implicitly changes + // key generator kind to KeyGeneratorKind.None for the hierarchies which key fields + // don't match certain conditions. + // Such "correction" makes Domain seem functional but exceptions can happen + // while working with domain. + + // This benifits in short term but in long term creates another "caviar" for user to remember + // along his project live, newcomers will probably not know this which can cause instability. + + Domain domain = null; + var configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.DefaultGeneratorSingleKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.DefaultGeneratorSingleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.PersistentInterfaceAsKey.DefaultGeneratorSingleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.DefaultGeneratorComplexKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.DefaultGeneratorComplexKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.PersistentInterfaceAsKey.DefaultGeneratorComplexKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.NamedDefaultGeneratorSingleKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.NamedDefaultGeneratorSingleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.PersistentInterfaceAsKey.NamedDefaultGeneratorSingleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.NamedDefaultGeneratorComplexKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.NamedDefaultGeneratorComplexKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.PersistentInterfaceAsKey.NamedDefaultGeneratorComplexKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.CustomGeneratorSingleKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity), + typeof(Models.PersistentInterfaceAsKey.SingleKeyGenerator) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.CustomGeneratorSingleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.PersistentInterfaceAsKey.CustomGeneratorSingleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.CustomGeneratorComplexKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity), + typeof(Models.PersistentInterfaceAsKey.ComplexKeyGenerator), + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.CustomGeneratorComplexKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.PersistentInterfaceAsKey.CustomGeneratorComplexKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.NoGeneratorSingleKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity) + }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.NoGeneratorSingleKeyEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + var keyEntity = new Models.PersistentInterfaceAsKey.SomeEntity(session); + _ = new Models.PersistentInterfaceAsKey.NoGeneratorSingleKeyEntity(session, keyEntity); // suppose to be this way + _ = new Models.PersistentInterfaceAsKey.NoGeneratorSingleKeyEntity(session); // tries to trigger generator + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.PersistentInterfaceAsKey.NoGeneratorComplexKeyEntity), + typeof(Models.PersistentInterfaceAsKey.ISomeEntity), + typeof(Models.PersistentInterfaceAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.PersistentInterfaceAsKey.NoGeneratorComplexKeyEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + var keyEntity = new Models.PersistentInterfaceAsKey.SomeEntity(session); + _ = new Models.PersistentInterfaceAsKey.NoGeneratorComplexKeyEntity(session, 123, keyEntity); // suppose to be this way + _ = new Models.PersistentInterfaceAsKey.NoGeneratorComplexKeyEntity(session); // tries to trigger generator + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + } + + [Test] + public void EntityAsKeyTest() + { + // NOTE!!! + // To make user's life easier on writing model classes DO implicitly changes + // key generator kind to KeyGeneratorKind.None for the hierarchies which key fields + // don't match certain conditions. + // Such "correction" makes Domain seem functional but exceptions can happen + // while working with domain. + + // This benifits in short term but in long term creates another "caviar" for user to remember + // along his project live, newcomers will probably not know this which can cause instability. + + Domain domain = null; + var configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.DefaultGeneratorSingleKeyEntity), + typeof(Models.EntityAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.EntityAsKey.DefaultGeneratorSingleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.EntityAsKey.DefaultGeneratorSingleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.DefaultGeneratorComplexKeyEntity), + typeof(Models.EntityAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.DefaultGeneratorComplexKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.EntityAsKey.DefaultGeneratorComplexKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.NamedDefaultGeneratorSingleKeyEntity), + typeof(Models.EntityAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.NamedDefaultGeneratorSingleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.EntityAsKey.NamedDefaultGeneratorSingleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.NamedDefaultGeneratorComplexKeyEntity), + typeof(Models.EntityAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.NamedDefaultGeneratorComplexKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.EntityAsKey.NamedDefaultGeneratorComplexKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.CustomGeneratorSingleKeyEntity), + typeof(Models.EntityAsKey.SomeEntity), + typeof(Models.EntityAsKey.SingleKeyGenerator) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.CustomGeneratorSingleKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.EntityAsKey.CustomGeneratorSingleKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.CustomGeneratorComplexKeyEntity), + typeof(Models.EntityAsKey.SomeEntity), + typeof(Models.EntityAsKey.ComplexKeyGenerator), + + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.CustomGeneratorComplexKeyEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.EntityAsKey.CustomGeneratorComplexKeyEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.NoGeneratorSingleKeyEntity), + typeof(Models.EntityAsKey.SomeEntity) + }); + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.NoGeneratorSingleKeyEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + var keyEntity = new Models.EntityAsKey.SomeEntity(session); + _ = new Models.EntityAsKey.NoGeneratorSingleKeyEntity(session, keyEntity); // suppose to be this way + _ = new Models.EntityAsKey.NoGeneratorSingleKeyEntity(session); // tries to trigger generator + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.EntityAsKey.NoGeneratorComplexKeyEntity), + typeof(Models.EntityAsKey.SomeEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.EntityAsKey.NoGeneratorComplexKeyEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + var keyEntity = new Models.EntityAsKey.SomeEntity(session); + _ = new Models.EntityAsKey.NoGeneratorComplexKeyEntity(session, 123, keyEntity); // suppose to be this way + _ = new Models.EntityAsKey.NoGeneratorComplexKeyEntity(session); // tries to trigger generator + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + } + + [Test] + public void ByteArrayKeyTest() + { + TestWithExceptionExpected(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.ByteArrayKeyEntity) }, + (ex) => ex.Message.Contains(CantBeOfMsg)); + } + + [Test] + public void IntArrayKeyTest() + { + TestWithExceptionExpected(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.IntArrayKeyEntity) }, + (ex) => ex.Message.Contains(CantBeOfMsg)); + } + + [Test] + public void ObjectKeyTest() + { + TestWithExceptionExpected(new[] { typeof(Models.NonPersistentStorageSupporedTypesAsKeys.ObjectKeyEntity) }, + (ex) => ex.Message.Contains("Unsupported type")); + } + + [Test] + public void LazyLoadKeyTest() + { + const string CannotBeLazyLoadMsg = "cannot be LazyLoad"; + + TestWithExceptionExpected(new[] { typeof(Models.LazyLoadKey.DefaultGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.LazyLoadKey.DefaultGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.LazyLoadKey.NamedDefaultGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.LazyLoadKey.NamedDefaultGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected( + new[] { typeof(Models.LazyLoadKey.CustomGeneratorSingleKeyEntity), typeof(Models.LazyLoadKey.SingleKeyGenerator) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected( + new[] { typeof(Models.LazyLoadKey.CustomGeneratorComplexKeyEntity), typeof(Models.LazyLoadKey.ComplexKeyGenerator) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.LazyLoadKey.NoGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.LazyLoadKey.NoGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CannotBeLazyLoadMsg))); + } + + [Test] + public void EntitySetKeyTest() + { + TestWithExceptionExpected(new[] { typeof(Models.EntitySetAsKey.DefaultGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.EntitySetAsKey.DefaultGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.EntitySetAsKey.NamedDefaultGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.EntitySetAsKey.NamedDefaultGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { typeof(Models.EntitySetAsKey.CustomGeneratorSingleKeyEntity), typeof(Models.EntitySetAsKey.SingleKeyGenerator) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { typeof(Models.EntitySetAsKey.CustomGeneratorComplexKeyEntity), typeof(Models.EntitySetAsKey.ComplexKeyGenerator) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.EntitySetAsKey.NoGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.EntitySetAsKey.NoGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + } + + [Test] + public void IEntityKeyTest() + { + TestWithExceptionExpected(new[] { typeof(Models.IEntityAsKey.DefaultGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.IEntityAsKey.DefaultGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.IEntityAsKey.NamedDefaultGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.IEntityAsKey.NamedDefaultGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected( + new[] { typeof(Models.IEntityAsKey.CustomGeneratorSingleKeyEntity), typeof(Models.IEntityAsKey.SingleKeyGenerator) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected( + new[] { typeof(Models.IEntityAsKey.CustomGeneratorComplexKeyEntity), typeof(Models.IEntityAsKey.ComplexKeyGenerator) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.IEntityAsKey.NoGeneratorSingleKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + + TestWithExceptionExpected(new[] { typeof(Models.IEntityAsKey.NoGeneratorComplexKeyEntity) }, + (ex) => Assert.That(ex.Message.Contains(UnsupportedTypeMsg))); + } + + [Test] + public void StructureKeyTest() + { + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.DefaultGeneratorSingleKeyEntity), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.DefaultGeneratorComplexKeyEntity), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.NamedDefaultGeneratorSingleKeyEntity), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.NamedDefaultGeneratorComplexKeyEntity), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.CustomGeneratorSingleKeyEntity), + typeof(Models.StructureAsKey.SingleKeyGenerator), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.CustomGeneratorComplexKeyEntity), + typeof(Models.StructureAsKey.ComplexKeyGenerator), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.NoGeneratorSingleKeyEntity), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + + TestWithExceptionExpected( + new[] { + typeof(Models.StructureAsKey.NoGeneratorComplexKeyEntity), + typeof(Models.StructureAsKey.Point) + }, + (ex) => Assert.That(ex.Message.Contains(CantBeOfMsg))); + } + + [Test] + public void NoKeyFieldsHierarchyTest() + { + TestWithExceptionExpected(typeof(Models.NoKeyFieldsHierarchy.NoKeyFieldsEntity), + (ex) => Assert.That(ex.Message.Contains("doesn't contain any key fields"))); + } + + [Test] + public void KeyNotInRootTest() + { + TestWithExceptionExpected( + new[] { + typeof(Models.KeyNotInRoot.DefaultGeneratorSingleKeyEntityRoot), + typeof(Models.KeyNotInRoot.DefaultGeneratorSingleKeyEntityLeaf) + }, + (ex) => Assert.That(ex.Message.Contains("doesn't contain any key fields"))); + + TestWithExceptionExpected( + new[] { + typeof(Models.KeyNotInRoot.NamedDefaultGeneratorSingleKeyEntityRoot), + typeof(Models.KeyNotInRoot.NamedDefaultGeneratorSingleKeyEntityLeaf) + }, + (ex) => Assert.That(ex.Message.Contains("doesn't contain any key fields"))); + + TestWithExceptionExpected( + new[] { + typeof(Models.KeyNotInRoot.CustomGeneratorSingleKeyEntityRoot), + typeof(Models.KeyNotInRoot.CustomGeneratorSingleKeyEntityLeaf), + typeof(Models.KeyNotInRoot.SingleKeyGenerator) + }, + (ex) => Assert.That(ex.Message.Contains("doesn't contain any key fields"))); + + TestWithExceptionExpected( + new[] { + typeof(Models.KeyNotInRoot.NoGeneratorSingleKeyEntityRoot), + typeof(Models.KeyNotInRoot.NoGeneratorSingleKeyEntityLeaf), + }, + (ex) => Assert.That(ex.Message.Contains("doesn't contain any key fields"))); + } + + [Test] + public void TwoKeysTest() + { + // NOTE!!! + // To make user's life easier on writing model classes DO implicitly changes + // key generator kind to KeyGeneratorKind.None for the hierarchies which key fields + // don't match certain conditions. + // Such "correction" makes Domain seem functional but exceptions can happen + // while working with domain. + + // This benifits in short term but in long term creates another "caviar" for user to remember + // along his project live, newcomers will probably not know this which can cause instability. + + Domain domain = null; + var configuration = CreateDomainConfiguration(new[] { typeof(Models.TwoKeys.DefaultGeneratorEntity) }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.TwoKeys.DefaultGeneratorEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.TwoKeys.DefaultGeneratorEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.TwoKeys.NamedGeneratorEntity) }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.TwoKeys.NamedGeneratorEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + var ex = Assert.Throws(() => { + _ = new Models.TwoKeys.NamedGeneratorEntity(session); + session.SaveChanges(); + }); + Assert.That(ex.Message.Contains(UnableToCreateKeyForMsg)); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.TwoKeys.CustomGeneratorEntity), + typeof(Models.TwoKeys.TwoKeyFieldsGen) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.TwoKeys.CustomGeneratorEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.Custom)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.TwoKeys.CustomGeneratorEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.TwoKeys.NoGeneratorEntity) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.TwoKeys.NoGeneratorEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.TwoKeys.NoGeneratorEntity(session, 1, 10); + session.SaveChanges(); + }); + } + } + + [Test] + public void SingleKeyWithTypeId() + { + Domain domain = null; + var configuration = CreateDomainConfiguration(new[] { typeof(Models.SingleKeyWithTypeId.DefaultGeneratorEntity) }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.SingleKeyWithTypeId.DefaultGeneratorEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.Default)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.SingleKeyWithTypeId.DefaultGeneratorEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.SingleKeyWithTypeId.NamedGeneratorEntity) }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.SingleKeyWithTypeId.NamedGeneratorEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.Default)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.SingleKeyWithTypeId.NamedGeneratorEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration( + new[] { + typeof(Models.SingleKeyWithTypeId.CustomGeneratorEntity), + typeof(Models.SingleKeyWithTypeId.SingleKeyGenerator) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.SingleKeyWithTypeId.CustomGeneratorEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.Custom)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.SingleKeyWithTypeId.CustomGeneratorEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration( + new[] { typeof(Models.SingleKeyWithTypeId.NoGeneratorEntity) }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.SingleKeyWithTypeId.NoGeneratorEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.SingleKeyWithTypeId.NoGeneratorEntity(session, 10); + session.SaveChanges(); + }); + } + } + + [Test] + public void ThreeKeysTest() + { + TestWithExceptionExpected(new[] { typeof(Models.ThreeKeys.DefaultGeneratorEntity) }, + ex => ex.Message.Contains(KeyGeneratorCanServeHierarchyWithOneKeyFieldMsg)); + + TestWithExceptionExpected(new[] { typeof(Models.ThreeKeys.NamedGeneratorEntity) }, + ex => ex.Message.Contains(KeyGeneratorCanServeHierarchyWithOneKeyFieldMsg)); + + Domain domain = null; + + var configuration = CreateDomainConfiguration( + new[] { + typeof(Models.ThreeKeys.CustomGeneratorEntity), + typeof(Models.ThreeKeys.TwoKeyFieldsGen) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.ThreeKeys.CustomGeneratorEntity)]; + + //generator kind is changed implicitly + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.Custom)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.ThreeKeys.CustomGeneratorEntity(session); + session.SaveChanges(); + }); + } + + configuration = CreateDomainConfiguration(new[] { typeof(Models.ThreeKeys.NoGeneratorEntity) }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + entityType = domain.Model.Types[typeof(Models.ThreeKeys.NoGeneratorEntity)]; + + Assert.That(entityType.Hierarchy.Key.GeneratorKind, Is.EqualTo(KeyGeneratorKind.None)); + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.ThreeKeys.NoGeneratorEntity(session, 1, 10, 100); + session.SaveChanges(); + }); + } + } + + [Test] + public void IModuleModifications() + { + // IModule manually adds existing TypeId column to key columns + + Domain domain = null; + var configuration = CreateDomainConfiguration(new[] { + typeof(Models.IModuleModifications.ManualIncludeTypeIdEntity), + typeof(Models.IModuleModifications.ModelDefModifier) + }); + + _ = Assert.Throws(() => domain = Domain.Build(configuration)); + + // IModule changes HierarhyRootDef.IncludeTypeId + configuration = CreateDomainConfiguration(new[] { + typeof(Models.IModuleModifications.IncludeTypeIdEntity), + typeof(Models.IModuleModifications.ModelDefModifier) + }); + + Assert.DoesNotThrow(() => domain = Domain.Build(configuration)); + Assert.That(domain, Is.Not.Null); + var entityType = domain.Model.Types[typeof(Models.IModuleModifications.IncludeTypeIdEntity)]; + + using (domain) + using (var session = domain.OpenSession()) + using (var tx = session.OpenTransaction()) { + Assert.DoesNotThrow(() => { + _ = new Models.IModuleModifications.IncludeTypeIdEntity(session); + session.SaveChanges(); + }); + } + } + + private void TestWithExceptionExpected(Type baseTypeFromNs, Action exceptionValidator) + where TException : Exception + { + var exceptionInstance = Assert.Throws(() => BuildDomainStructureOnly(CreateDomainConfiguration(baseTypeFromNs))); + exceptionValidator?.Invoke(exceptionInstance); + } + + private void TestWithExceptionExpected(Type[] typesToRegister, Action exceptionValidator) + where TException : Exception + { + var exceptionInstance = Assert.Throws(() => BuildDomainStructureOnly(CreateDomainConfiguration(typesToRegister))); + exceptionValidator?.Invoke(exceptionInstance); + } + + private DomainConfiguration CreateDomainConfiguration(Type baseTypeFromNs) + { + var configuration = DomainConfigurationFactory.Create(); + configuration.UpgradeMode = DomainUpgradeMode.Recreate; + configuration.Types.Register(baseTypeFromNs.Assembly, baseTypeFromNs.Namespace); + return configuration; + } + + private DomainConfiguration CreateDomainConfiguration(Type[] typesToRegister) + { + var configuration = DomainConfigurationFactory.Create(); + configuration.UpgradeMode = DomainUpgradeMode.Recreate; + foreach(var t in typesToRegister) { + configuration.Types.Register(t); + } + return configuration; + } + + private Domain BuildDomainStructureOnly(DomainConfiguration domainConfiguration) + { + var upgradeContext = new Orm.Upgrade.UpgradeContext(domainConfiguration); + + using (upgradeContext.Activate()) + using (upgradeContext.Services) { + var configuration = CreateDomainBuilderConfiguration(upgradeContext); + return DomainBuilder.Run(configuration); + } + } + + private DomainBuilderConfiguration CreateDomainBuilderConfiguration(Orm.Upgrade.UpgradeContext upgradeContext) + { + var services = upgradeContext.Services; + + BuildServices(services, upgradeContext.Configuration); + + var configuration = new DomainBuilderConfiguration { + DomainConfiguration = upgradeContext.Configuration, + Stage = Orm.Upgrade.UpgradeStage.Final, + Services = services, + ModelFilter = new Orm.Upgrade.StageModelFilter(services.UpgradeHandlers, Orm.Upgrade.UpgradeStage.Final), + UpgradeContextCookie = new object(), + RecycledDefinitions = new List(), + DefaultSchemaInfo = new Sql.Info.DefaultSchemaInfo("dummyDb", "dummySchema") + }; + + configuration.Lock(); + return configuration; + } + + private void BuildServices(Orm.Upgrade.UpgradeServiceAccessor services, DomainConfiguration configuration) + { + services.Configuration = configuration; + services.IndexFilterCompiler = new Providers.PartialIndexFilterCompiler(); + + var descriptor = ProviderDescriptor.Get(configuration.ConnectionInfo.Provider); + var driverFactory = (Sql.SqlDriverFactory) Activator.CreateInstance(descriptor.DriverFactory); + var handlerFactory = (Providers.HandlerFactory) Activator.CreateInstance(descriptor.HandlerFactory); + var driver = Providers.StorageDriver.Create(driverFactory, configuration); + services.HandlerFactory = handlerFactory; + services.StorageDriver = driver; + services.NameBuilder = new Providers.NameBuilder(configuration, driver.ProviderInfo); + + + var dummyDefaultSchemaInfo = new Sql.Info.DefaultSchemaInfo("dummyDb", "dummySchema"); + services.MappingResolver = new Providers.SimpleMappingResolver(dummyDefaultSchemaInfo); + BuildExternalServices(services, configuration); + services.Lock(); + } + + private void BuildExternalServices(Orm.Upgrade.UpgradeServiceAccessor serviceAccessor, DomainConfiguration configuration) + { + var standardRegistrations = new[] { + new ServiceRegistration(typeof (DomainConfiguration), configuration), + //new ServiceRegistration(typeof (Orm.Upgrade.UpgradeContext), context) + }; + + var handlers = configuration.Types.UpgradeHandlers + .Select(type => new ServiceRegistration(typeof(Orm.Upgrade.IUpgradeHandler), type, false)); + + var registrations = standardRegistrations.Concat(handlers); + var serviceContainer = new ServiceContainer(registrations); + serviceAccessor.RegisterResource(serviceContainer); + + BuildModules(serviceAccessor); + BuildUpgradeHandlers(serviceAccessor, serviceContainer); + } + + private static void BuildModules(Orm.Upgrade.UpgradeServiceAccessor serviceAccessor) + { + serviceAccessor.Modules = new List().AsReadOnly(); + } + + private static void BuildUpgradeHandlers(Orm.Upgrade.UpgradeServiceAccessor serviceAccessor, IServiceContainer serviceContainer) + { + // Getting user handlers + var userHandlers = + from handler in serviceContainer.GetAll() + let assembly = handler.Assembly ?? handler.GetType().Assembly + where handler.IsEnabled + group handler by assembly; + + // Adding user handlers + var handlers = new Dictionary(); + foreach (var group in userHandlers) { + var candidates = group.ToList(); + if (candidates.Count > 1) { + throw new DomainBuilderException( + string.Format(Strings.ExMoreThanOneEnabledXIsProvidedForAssemblyY, typeof(Orm.Upgrade.IUpgradeHandler).Name, @group.Key)); + } + handlers.Add(group.Key, candidates[0]); + } + + // Adding default handlers + var assembliesWithUserHandlers = handlers.Select(pair => pair.Key); + var assembliesWithoutUserHandler = + serviceAccessor.Configuration.Types.PersistentTypes + .Select(type => type.Assembly) + .Distinct() + .Except(assembliesWithUserHandlers); + + foreach (var assembly in assembliesWithoutUserHandler) { + var handler = new Orm.Upgrade.UpgradeHandler(assembly); + handlers.Add(assembly, handler); + } + + // Building a list of handlers sorted by dependencies of their assemblies + var dependencies = handlers.Keys.ToDictionary( + assembly => assembly, + assembly => assembly.GetReferencedAssemblies().Select(assemblyName => assemblyName.ToString()).ToHashSet()); + var sortedHandlers = handlers + .SortTopologically((a0, a1) => dependencies[a1.Key].Contains(a0.Key.GetName().ToString())) + .Select(pair => pair.Value); + + // Storing the result + serviceAccessor.UpgradeHandlers = new ReadOnlyDictionary(handlers); + serviceAccessor.OrderedUpgradeHandlers = sortedHandlers.ToList().AsReadOnly(); + } + } +} + +namespace Xtensive.Orm.Tests.Model.HierarchyRootValidationTestModel +{ + namespace NonPersistentStorageSupporedTypesAsKeys + { + [HierarchyRoot] + public class ByteKeyEntity : Entity + { + [Field] + [Key] + public byte Id { get; private set; } + + [Field] + public int Value { get; set; } + + public ByteKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class Int16KeyEntity : Entity + { + [Field] + [Key] + public short Id { get; private set; } + + [Field] + public int Value { get; set; } + + public Int16KeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class UInt16KeyEntity : Entity + { + [Field] + [Key] + public ushort Id { get; private set; } + + [Field] + public int Value { get; set; } + + public UInt16KeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class Int32KeyEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public int Value { get; set; } + + public Int32KeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class UInt32KeyEntity : Entity + { + [Field] + [Key] + public uint Id { get; private set; } + + [Field] + public int Value { get; set; } + + public UInt32KeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class Int64KeyEntity : Entity + { + [Field] + [Key] + public long Id { get; private set; } + + [Field] + public int Value { get; set; } + + public Int64KeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class UInt64KeyEntity : Entity + { + [Field] + [Key] + public ulong Id { get; private set; } + + [Field] + public int Value { get; set; } + + public UInt64KeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class FloatKeyEntity : Entity + { + [Field] + [Key] + public float Id { get; private set; } + + [Field] + public int Value { get; set; } + + public FloatKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class DoubleKeyEntity : Entity + { + [Field] + [Key] + public double Id { get; private set; } + + [Field] + public int Value { get; set; } + + public DoubleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class DecimalKeyEntity : Entity + { + [Field(Precision = 12, Scale = 0)] + [Key] + public decimal Id { get; private set; } + + [Field] + public int Value { get; set; } + + public DecimalKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class FractionalDecimalKeyEntity : Entity + { + [Field(Precision = 12, Scale = 3)] + [Key] + public decimal Id { get; private set; } + + [Field] + public int Value { get; set; } + + public FractionalDecimalKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class TimeSpanKeyEntity : Entity + { + [Field] + [Key] + public TimeSpan Id { get; private set; } + + [Field] + public int Value { get; set; } + + public TimeSpanKeyEntity(Session session) + : base(session) + { + } + } + +#if NET6_0_OR_GREATER + + [HierarchyRoot] + public class TimeOnlyKeyEntity : Entity + { + [Field] + [Key] + public TimeOnly Id { get; private set; } + + [Field] + public int Value { get; set; } + + public TimeOnlyKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class DateOnlyKeyEntity : Entity + { + [Field] + [Key] + public DateOnly Id { get; private set; } + + [Field] + public int Value { get; set; } + + public DateOnlyKeyEntity(Session session) + : base(session) + { + } + } + +#endif + + [HierarchyRoot] + public class DateTimeKeyEntity : Entity + { + [Field] + [Key] + public DateTime Id { get; private set; } + + [Field] + public int Value { get; set; } + + public DateTimeKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class DateTimeOffsetKeyEntity : Entity + { + [Field] + [Key] + public DateTimeOffset Id { get; private set; } + + [Field] + public int Value { get; set; } + + public DateTimeOffsetKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class CharKeyEntity : Entity + { + [Field] + [Key] + public char Id { get; private set; } + + [Field] + public int Value { get; set; } + + public CharKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class LimitedStringKeyEntity : Entity + { + [Field(Length = 255)] + [Key] + public string Id { get; private set; } + + [Field] + public int Value { get; set; } + + public LimitedStringKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class StringKeyEntity : Entity + { + [Field] + [Key] + public string Id { get; private set; } + + [Field] + public int Value { get; set; } + + public StringKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class GuidKeyEntity : Entity + { + [Field] + [Key] + public Guid Id { get; private set; } + + [Field] + public int Value { get; set; } + + public GuidKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class ByteArrayKeyEntity : Entity + { + [Field] + [Key] + public byte[] Id { get; private set; } + + [Field] + public int Value { get; set; } + + public ByteArrayKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class IntArrayKeyEntity : Entity + { + [Field] + [Key] + public int[] Id { get; private set; } + + [Field] + public int Value { get; set; } + + public IntArrayKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class ObjectKeyEntity : Entity + { + [Field] + [Key] + public object Id { get; private set; } + + [Field] + public int Value { get; set; } + + public ObjectKeyEntity(Session session) + : base(session) + { + } + } + } + + namespace NonPersistentComplexKey + { + [HierarchyRoot] + public class ByteKeyEntity : Entity + { + [Field] + [Key(0)] + public byte Id1 { get; private set; } + + [Field] + [Key(1)] + public byte Id2 { get; private set; } + + [Field] + public int Value { get; set; } + + public ByteKeyEntity(Session session) + : base(session) + { + } + } + } + + namespace LazyLoadKey + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntity : Entity + { + [Field(LazyLoad = true)] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntity : Entity + { + [Field(LazyLoad = true)] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntity : Entity + { + [Field(LazyLoad = true)] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntity : Entity + { + [Field(LazyLoad = true)] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field(LazyLoad = true)] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field(LazyLoad = true)] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(ComplexKeyGenerator))] + public class CustomGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field(LazyLoad = true)] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field(LazyLoad = true)] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + } + + namespace EntityAsKey + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + [HierarchyRoot] + public class SomeEntity : Entity + { + [Field, Key] + public int Id { get; private set; } + + public SomeEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public SomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public SomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedDefaultGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public SomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public SomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + + public NoGeneratorSingleKeyEntity(Session session, SomeEntity id) + : base(session, id) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public SomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public SomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedDefaultGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(ComplexKeyGenerator))] + public class CustomGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public SomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public SomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + + public NoGeneratorComplexKeyEntity(Session session, int id1, SomeEntity id2) + : base(session, id1, id2) + { + } + } + } + + namespace PersistentInterfaceAsKey + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + public interface ISomeEntity : IEntity + { + [Field] + int Id { get; } + + [Field] + string Name { get; set; } + } + + [HierarchyRoot] + public class SomeEntity : Entity, ISomeEntity + { + [Field, Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public SomeEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public ISomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public ISomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedDefaultGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public ISomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public ISomeEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorSingleKeyEntity(Session session) + : base(session) + { + } + + public NoGeneratorSingleKeyEntity(Session session, ISomeEntity id) + : base(session, id) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public ISomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public ISomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedDefaultGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(ComplexKeyGenerator))] + public class CustomGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public ISomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public ISomeEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorComplexKeyEntity(Session session) + : base(session) + { + } + + public NoGeneratorComplexKeyEntity(Session session, int id1, ISomeEntity id2) + : base(session, id1, id2) + { + } + } + } + + namespace EntitySetAsKey + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + [HierarchyRoot] + public class SomeEntity : Entity + { + [Field, Key] + public int Id { get; private set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public EntitySet Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public EntitySet Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public EntitySet Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public EntitySet Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public EntitySet Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public EntitySet Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(ComplexKeyGenerator))] + public class CustomGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public EntitySet Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public EntitySet Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + } + + namespace IEntityAsKey + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public IEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public IEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public IEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public IEntity Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public IEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public IEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(ComplexKeyGenerator))] + public class CustomGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public IEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public IEntity Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + } + + namespace StructureAsKey + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + public class Point : Structure + { + [Field] + public int X { get; set; } + + [Field] + public int Y { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public Point Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public Point Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public Point Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntity : Entity + { + [Field] + [Key] + public Point Id { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public Point Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntity))] // pretty much default generator + public class NamedDefaultGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public Point Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(ComplexKeyGenerator))] + public class CustomGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public Point Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorComplexKeyEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public Point Id2 { get; private set; } + + [Field] + public string Name { get; set; } + } + } + + namespace NoKeyFieldsHierarchy + { + [HierarchyRoot] + public class NoKeyFieldsEntity : Entity + { + [Field] + //No Key Attribute! + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + } + } + + namespace KeyNotInRoot + { + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++); + } + } + + [Service(typeof(KeyGenerator), Name = nameof(ComplexKeyGenerator))] + public sealed class ComplexKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var now = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, now.Minute); + } + } + + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorSingleKeyEntityRoot : Entity + { + [Field] + public string Name { get; set; } + } + + public class DefaultGeneratorSingleKeyEntityLeaf : DefaultGeneratorSingleKeyEntityRoot + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name2 { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedDefaultGeneratorSingleKeyEntityRoot))] // pretty much default generator + public class NamedDefaultGeneratorSingleKeyEntityRoot : Entity + { + [Field] + public string Name { get; set; } + } + + public class NamedDefaultGeneratorSingleKeyEntityLeaf : NamedDefaultGeneratorSingleKeyEntityRoot + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name2 { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorSingleKeyEntityRoot : Entity + { + [Field] + public string Name { get; set; } + } + + public class CustomGeneratorSingleKeyEntityLeaf : CustomGeneratorSingleKeyEntityRoot + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name2 { get; set; } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorSingleKeyEntityRoot : Entity + { + [Field] + public string Name { get; set; } + } + + public class NoGeneratorSingleKeyEntityLeaf : NoGeneratorSingleKeyEntityRoot + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name2 { get; set; } + } + } + + namespace TwoKeys + { + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedGeneratorEntity))] // still defaut key generator capabilities but dedicated instance + public class NamedGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedGeneratorEntity(Session session) + : base(session) + { + } + } + + [Service(typeof(KeyGenerator), Name = nameof(TwoKeyFieldsGen))] + public sealed class TwoKeyFieldsGen : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + return Tuples.Tuple.Create(counter1++, DateTime.UtcNow.Minute); + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(TwoKeyFieldsGen))] + public class CustomGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorEntity(Session session, int id1, int id2) + : base(session, id1, id2) + { + } + } + } + + namespace SingleKeyWithTypeId + { + [HierarchyRoot(IncludeTypeId = true)] // this setting doesn't cause addtional keyField on HierarchyDef level + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot(IncludeTypeId = true)] // this setting doesn't cause addtional keyField on HierarchyDef level + [KeyGenerator(Name = nameof(NamedGeneratorEntity))] // pretty much default generator + public class NamedGeneratorEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedGeneratorEntity(Session session) + : base(session) + { + } + } + + [Service(typeof(KeyGenerator), Name = nameof(SingleKeyGenerator))] + public sealed class SingleKeyGenerator : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + if (keyInfo.TypeIdColumnIndex >= 0) { + return Tuples.Tuple.Create(counter1++, -1);// -1 will be replaced with actual TypeId value + } + return Tuples.Tuple.Create(counter1++); + } + } + + [HierarchyRoot(IncludeTypeId = true)] // this setting doesn't cause addtional keyField on HierarchyDef level + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(SingleKeyGenerator))] + public class CustomGeneratorEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot(IncludeTypeId = true)] // this setting doesn't cause addtional keyField on HierarchyDef level + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorEntity(Session session, int id) + : base(session, id) + { + } + } + } + + namespace ThreeKeys + { + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Default)] // equals no attribute at all, added for clearance + public class DefaultGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + [Key(2)] + public int Id3 { get; private set; } + + [Field] + public string Name { get; set; } + + public DefaultGeneratorEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(Name = nameof(NamedGeneratorEntity))] // still defaut key generator capabilities but dedicated instance + public class NamedGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + [Key(2)] + public int Id3 { get; private set; } + + [Field] + public string Name { get; set; } + + public NamedGeneratorEntity(Session session) + : base(session) + { + } + } + + [Service(typeof(KeyGenerator), Name = nameof(TwoKeyFieldsGen))] + public sealed class TwoKeyFieldsGen : KeyGenerator + { + private int counter1; + + public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor) + { + } + + public override Tuples.Tuple GenerateKey(KeyInfo keyInfo, Session session) + { + var utcNow = DateTime.UtcNow; + return Tuples.Tuple.Create(counter1++, utcNow.Minute, utcNow.Second); + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.Custom, Name = nameof(TwoKeyFieldsGen))] + public class CustomGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + [Key(2)] + public int Id3 { get; private set; } + + [Field] + public string Name { get; set; } + + public CustomGeneratorEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + [KeyGenerator(KeyGeneratorKind.None)] + public class NoGeneratorEntity : Entity + { + [Field] + [Key(0)] + public int Id1 { get; private set; } + + [Field] + [Key(1)] + public int Id2 { get; private set; } + + [Field] + [Key(2)] + public int Id3 { get; private set; } + + [Field] + public string Name { get; set; } + + public NoGeneratorEntity(Session session, int id1, int id2, int id3) + : base(session, id1, id2, id3) + { + } + } + } + + namespace IModuleModifications + { + public class ModelDefModifier : IModule2 + { + public void OnAutoGenericsBuilt(BuildingContext context, ICollection autoGenerics) + { + + } + public void OnBuilt(Domain domain) + { + + } + public void OnDefinitionsBuilt(BuildingContext context, DomainModelDef model) + { + var manualIncludeTypeIdHierarchy = model.Hierarchies.TryGetValue(typeof(ManualIncludeTypeIdEntity)); + if (manualIncludeTypeIdHierarchy is not null) { + var rootType = manualIncludeTypeIdHierarchy.Root; + manualIncludeTypeIdHierarchy.KeyFields.Add(new KeyField(WellKnown.TypeIdFieldName)); + } + + var includeTypeIdHierarchy = model.Hierarchies.TryGetValue(typeof(IncludeTypeIdEntity)); + if (includeTypeIdHierarchy is not null) { + includeTypeIdHierarchy.IncludeTypeId = true; + } + } + } + + [HierarchyRoot] + public class ManualIncludeTypeIdEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public ManualIncludeTypeIdEntity(Session session) + : base(session) + { + } + } + + [HierarchyRoot] + public class IncludeTypeIdEntity : Entity + { + [Field] + [Key] + public int Id { get; private set; } + + [Field] + public string Name { get; set; } + + public IncludeTypeIdEntity(Session session) + : base(session) + { + } + } + } +} From 607773501fccdb7ec89304f739143510f8710b81 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 20 Jan 2025 16:03:59 +0500 Subject: [PATCH 11/23] Explicitlly set KeyGeneratorKind.None instead of implicit conversion --- Orm/Xtensive.Orm.Tests/Issues/IssueJira0555_KeyRemapBug.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0555_KeyRemapBug.cs b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0555_KeyRemapBug.cs index be8fe1b2ac..a66363cfcf 100644 --- a/Orm/Xtensive.Orm.Tests/Issues/IssueJira0555_KeyRemapBug.cs +++ b/Orm/Xtensive.Orm.Tests/Issues/IssueJira0555_KeyRemapBug.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Xtensive LLC. +// Copyright (C) 2014 Xtensive LLC. // All rights reserved. // For conditions of distribution and use, see license. // Created by: Alexey Kulakov @@ -57,7 +57,7 @@ public class TestEntity : Entity } [HierarchyRoot] - [KeyGenerator] + [KeyGenerator(KeyGeneratorKind.None)] public class TestEntity2 : Entity { private static int Increment = 1; From 5a807f309bf03a4392be7edaea243e9c4f09813f Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 20 Jan 2025 16:58:31 +0500 Subject: [PATCH 12/23] Write warning to build log about change of generator kind --- .../Orm/Building/Builders/TypeBuilder.cs | 4 +++ Orm/Xtensive.Orm/Strings.Designer.cs | 33 +++++++------------ Orm/Xtensive.Orm/Strings.resx | 3 ++ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs b/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs index 0db467dc80..01323e828a 100644 --- a/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs +++ b/Orm/Xtensive.Orm/Orm/Building/Builders/TypeBuilder.cs @@ -527,6 +527,10 @@ private KeyInfo BuildKeyInfo(TypeInfo root, HierarchyDef hierarchyDef) } } + if (generatorKind != hierarchyDef.KeyGeneratorKind && generatorKind == KeyGeneratorKind.None) { + BuildLog.Warning(string.Format(Strings.LogKeyGeneratorKindForHierarchyWithRootXHasChangedToNone, root.Name)); + } + if (generatorKind == KeyGeneratorKind.None) { // No key generator is attached. // Each hierarchy has it's own equality identifier. diff --git a/Orm/Xtensive.Orm/Strings.Designer.cs b/Orm/Xtensive.Orm/Strings.Designer.cs index 13985efb13..fb5b8db136 100644 --- a/Orm/Xtensive.Orm/Strings.Designer.cs +++ b/Orm/Xtensive.Orm/Strings.Designer.cs @@ -2588,15 +2588,6 @@ internal static string ExJoinHasSameInnerAndOuterParameterInstances { } } - /// - /// Looks up a localized string similar to Key already exists.. - /// - internal static string ExKeyAlreadyExists { - get { - return ResourceManager.GetString("ExKeyAlreadyExists", resourceCulture); - } - } - /// /// Looks up a localized string similar to The Key belongs to different storage node.. /// @@ -4669,15 +4660,6 @@ internal static string ExTypeXShouldNotBeGeneric { } } - /// - /// Looks up a localized string similar to Query was compiled with DomainConfiguration.ShareStorageSchemaOverNodes option set to true, it requires PostCompilerConfiguration.SchemaMapping and PostCompilerConfiguration.DatabaseMapping collections to be provided.. - /// - internal static string ExUnableToActualizeSchemaNodeInQuery { - get { - return ResourceManager.GetString("ExUnableToActualizeSchemaNodeInQuery", resourceCulture); - } - } - /// /// Looks up a localized string similar to The type '{0}',which contains renaming field '{1}', doesn't exist in storage model.. /// @@ -4688,11 +4670,11 @@ internal static string ExTypeXWhichContainsRenamingFieldYDoesntExistInStorageMod } /// - /// Looks up a localized string similar to Unable to activate EntitySet for '{0}' field because it does not has association.. + /// Looks up a localized string similar to Query was compiled with DomainConfiguration.ShareStorageSchemaOverNodes option set to true, it requires PostCompilerConfiguration.SchemaMapping and PostCompilerConfiguration.DatabaseMapping collections to be provided.. /// - internal static string ExUnableToActivateEntitySetWithoutAssociation { + internal static string ExUnableToActualizeSchemaNodeInQuery { get { - return ResourceManager.GetString("ExUnableToActivateEntitySetWithoutAssociation", resourceCulture); + return ResourceManager.GetString("ExUnableToActualizeSchemaNodeInQuery", resourceCulture); } } @@ -6123,6 +6105,15 @@ internal static string LogItemFormat { } } + /// + /// Looks up a localized string similar to Key generator kind for hierarchy with root '{0}' has changed to None. Make sure that all key values are recieved by constructor and passed to one of Entity constructors.. + /// + internal static string LogKeyGeneratorKindForHierarchyWithRootXHasChangedToNone { + get { + return ResourceManager.GetString("LogKeyGeneratorKindForHierarchyWithRootXHasChangedToNone", resourceCulture); + } + } + /// /// Looks up a localized string similar to Metadata.Assembly created: '{0}'.. /// diff --git a/Orm/Xtensive.Orm/Strings.resx b/Orm/Xtensive.Orm/Strings.resx index 2419b0e101..aeda139b77 100644 --- a/Orm/Xtensive.Orm/Strings.resx +++ b/Orm/Xtensive.Orm/Strings.resx @@ -2609,4 +2609,7 @@ Error: {1} Translation of TimeOnly.ToString(string) with arbitrary arguments is not supported. Use TimeOnly.ToString("s"). + + Key generator kind for hierarchy with root '{0}' has changed to None. Make sure that all key values are recieved by constructor and passed to one of Entity constructors. + \ No newline at end of file From 8b9f50d36844c30354f49af8272d358f17b74774 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Tue, 21 Jan 2025 16:26:34 +0500 Subject: [PATCH 13/23] caviar->caveat in comments --- .../Model/HierarchyRootValidationTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs b/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs index aecea0931c..277aaeae5e 100644 --- a/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs +++ b/Orm/Xtensive.Orm.Tests/Model/HierarchyRootValidationTest.cs @@ -164,7 +164,7 @@ public void InvalidNonPersistentKeyTypesForDefaultGeneratorTest() // Such "correction" makes Domain seem functional but exceptions can happen // while working with domain. - // This benifits in short term but in long term creates another "caviar" for user to remember + // This benifits in short term but in long term creates another caveat for user to remember // along his project live, newcomers will probably not know this which can cause instability. Domain domain = null; @@ -363,7 +363,7 @@ public void NonPersistentComplexKeyTest() // Such "correction" makes Domain seem functional but exceptions can happen // while working with domain. - // This benifits in short term but in long term creates another "caviar" for user to remember + // This benifits in short term but in long term creates another caveat for user to remember // along his project live, newcomers will probably not know this which can cause instability. Domain domain = null; @@ -396,7 +396,7 @@ public void PersistentInterfaceKeyTest() // Such "correction" makes Domain seem functional but exceptions can happen // while working with domain. - // This benifits in short term but in long term creates another "caviar" for user to remember + // This benifits in short term but in long term creates another caveat for user to remember // along his project live, newcomers will probably not know this which can cause instability. Domain domain = null; @@ -606,7 +606,7 @@ public void EntityAsKeyTest() // Such "correction" makes Domain seem functional but exceptions can happen // while working with domain. - // This benifits in short term but in long term creates another "caviar" for user to remember + // This benifits in short term but in long term creates another caveat for user to remember // along his project live, newcomers will probably not know this which can cause instability. Domain domain = null; @@ -1024,7 +1024,7 @@ public void TwoKeysTest() // Such "correction" makes Domain seem functional but exceptions can happen // while working with domain. - // This benifits in short term but in long term creates another "caviar" for user to remember + // This benifits in short term but in long term creates another caveat for user to remember // along his project live, newcomers will probably not know this which can cause instability. Domain domain = null; From f87d243d341dd8dca24bd4df1b1b236441233a6d Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Tue, 21 Jan 2025 18:09:48 +0500 Subject: [PATCH 14/23] Improve changelog --- ChangeLog/7.1.4_dev.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog/7.1.4_dev.txt b/ChangeLog/7.1.4_dev.txt index 129c659ad1..754f28c4ee 100644 --- a/ChangeLog/7.1.4_dev.txt +++ b/ChangeLog/7.1.4_dev.txt @@ -1 +1,2 @@ -[main] Addressed IndexOutOfRangeException on translation of certain queries with aggregates \ No newline at end of file +[main] Addressed IndexOutOfRangeException on translation of certain queries with aggregates +[main] Notification to BuildLog when a hierarchy changes KeyGeneratorKind value to None \ No newline at end of file From 0da23caa53f49c9d40da098075579208c771bb99 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 22 Jan 2025 12:43:55 +0500 Subject: [PATCH 15/23] Fix misspelling of "Length" --- .../KeyValuePairInstanceGenerator.cs | 8 +-- .../Storage/SkippingValidationOnCommitTest.cs | 50 +++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests.Framework/Internals/KeyValuePairInstanceGenerator.cs b/Orm/Xtensive.Orm.Tests.Framework/Internals/KeyValuePairInstanceGenerator.cs index f8e5d0be4e..79e6124325 100644 --- a/Orm/Xtensive.Orm.Tests.Framework/Internals/KeyValuePairInstanceGenerator.cs +++ b/Orm/Xtensive.Orm.Tests.Framework/Internals/KeyValuePairInstanceGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2003-2010 Xtensive LLC. +// Copyright (C) 2003-2010 Xtensive LLC. // All rights reserved. // For conditions of distribution and use, see license. // Created by: Alex Yakunin @@ -13,13 +13,13 @@ namespace Xtensive.Orm.Tests [Serializable] internal class ArrayInstanceGenerator: WrappingInstanceGenerator { - public const int ArrayLenght = 100; + public const int ArrayLength = 100; public override T[] GetInstance(Random random) { - T[] result = new T[ArrayLenght]; + T[] result = new T[ArrayLength]; int i = 0; - foreach (T t in BaseGenerator.GetInstances(random, ArrayLenght)) { + foreach (T t in BaseGenerator.GetInstances(random, ArrayLength)) { result[i] = t; i++; } diff --git a/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs b/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs index 5b5b7ab428..ac63ff687a 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs @@ -45,10 +45,10 @@ protected override void PopulateData() _ = new FutureTestEntity3() { NeverValidatedField = "Future", DateField = DateTime.Now.AddMonths(-1) }; _ = new FutureTestEntity4() { NeverValidatedField = "Future", DateField = DateTime.Now.AddMonths(-1) }; - _ = new LenghtTestEntity1() { NeverValidatedField = "Length", StringField = "too short" }; - _ = new LenghtTestEntity2() { NeverValidatedField = "Length", StringField = "too short" }; - _ = new LenghtTestEntity3() { NeverValidatedField = "Length", StringField = "too short" }; - _ = new LenghtTestEntity4() { NeverValidatedField = "Length", StringField = "too short" }; + _ = new LengthTestEntity1() { NeverValidatedField = "Length", StringField = "too short" }; + _ = new LengthTestEntity2() { NeverValidatedField = "Length", StringField = "too short" }; + _ = new LengthTestEntity3() { NeverValidatedField = "Length", StringField = "too short" }; + _ = new LengthTestEntity4() { NeverValidatedField = "Length", StringField = "too short" }; _ = new NotEmptyTestEntity1() { NeverValidatedField = "NotEmpty", StringField = string.Empty }; _ = new NotEmptyTestEntity2() { NeverValidatedField = "NotEmpty", StringField = string.Empty }; @@ -383,21 +383,21 @@ public void LenghtConstraintImmediateNotSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => entity.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => session.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; var errors = session.ValidateAndGetErrors(); Assert.That(errors.Count, Is.EqualTo(1)); @@ -406,7 +406,7 @@ public void LenghtConstraintImmediateNotSkippedTest() _ = Assert.Throws(() => { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; transaction.Complete(); //exception on commit @@ -419,21 +419,21 @@ public void LenghtConstraintImmediateSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => entity.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => session.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; var errors = session.ValidateAndGetErrors(); Assert.That(errors.Count, Is.EqualTo(1)); @@ -441,7 +441,7 @@ public void LenghtConstraintImmediateSkippedTest() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; transaction.Complete(); //no exception on commit @@ -453,21 +453,21 @@ public void LenghtConstraintNotImmidiateNotSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => entity.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => session.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; var errors = session.ValidateAndGetErrors(); Assert.That(errors.Count, Is.EqualTo(1)); @@ -476,7 +476,7 @@ public void LenghtConstraintNotImmidiateNotSkippedTest() _ = Assert.Throws(() => { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; transaction.Complete(); //exception on commit @@ -489,21 +489,21 @@ public void LenghtConstraintNotImmediateSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => entity.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; _ = Assert.Throws(() => session.Validate()); } using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; var errors = session.ValidateAndGetErrors(); Assert.That(errors.Count, Is.EqualTo(1)); @@ -511,7 +511,7 @@ public void LenghtConstraintNotImmediateSkippedTest() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var entity = session.Query.All().First(); + var entity = session.Query.All().First(); entity.NeverValidatedField += "(changed)"; transaction.Complete(); //no exception on commit @@ -519,7 +519,7 @@ public void LenghtConstraintNotImmediateSkippedTest() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - _ = new LenghtTestEntity4() { NeverValidatedField = "", StringField = "not email" };//no exception + _ = new LengthTestEntity4() { NeverValidatedField = "", StringField = "not email" };//no exception transaction.Complete(); // no exception } @@ -1446,7 +1446,7 @@ public class FutureTestEntity1 : BaseEntity } [HierarchyRoot] - public class LenghtTestEntity1 : BaseEntity + public class LengthTestEntity1 : BaseEntity { [Field] [LengthConstraint(IsImmediate = true, Min = 16)] @@ -1522,7 +1522,7 @@ public class FutureTestEntity2 : BaseEntity } [HierarchyRoot] - public class LenghtTestEntity2 : BaseEntity + public class LengthTestEntity2 : BaseEntity { [Field] [LengthConstraint(IsImmediate = true, SkipOnTransactionCommit = true, Min = 16)] @@ -1598,7 +1598,7 @@ public class FutureTestEntity3 : BaseEntity } [HierarchyRoot] - public class LenghtTestEntity3 : BaseEntity + public class LengthTestEntity3 : BaseEntity { [Field] [LengthConstraint(IsImmediate = false, Min = 16)] @@ -1674,7 +1674,7 @@ public class FutureTestEntity4 : BaseEntity } [HierarchyRoot] - public class LenghtTestEntity4 : BaseEntity + public class LengthTestEntity4 : BaseEntity { [Field] [LengthConstraint(IsImmediate = false, SkipOnTransactionCommit = true, Min = 16)] From d487fb60946b300c892d16f8012e91a72b2edfa5 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 22 Jan 2025 12:55:13 +0500 Subject: [PATCH 16/23] Remove commented code --- Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs index 39b6012e17..bba697a80b 100644 --- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs +++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs @@ -101,7 +101,6 @@ public override void Translate(IOutput output, SqlFunctionType type) case SqlFunctionType.CurrentUser: _ = output.Append("CURRENT_USER()"); break; case SqlFunctionType.SessionUser: _ = output.Append("SESSION_USER()"); break; - //case SqlFunctionType.NullIf: _ = output.Append("IFNULL"); break; //datetime/timespan case SqlFunctionType.DateTimeTruncate: _ = output.Append("DATE"); break; case SqlFunctionType.CurrentDate: _ = output.Append("CURDATE()"); break; From e77d2eccf3f492bdcfdee19ece2a0194e78213ef Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 22 Jan 2025 13:03:53 +0500 Subject: [PATCH 17/23] Rename function --- Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs index 14580f4c92..b7b5823f8e 100644 --- a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs +++ b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs @@ -155,7 +155,7 @@ public override void Visit(SqlFunctionCall node) return; case SqlFunctionType.PadLeft: case SqlFunctionType.PadRight: - Visit(EmulateLpadOrRpad(arguments, node.FunctionType is SqlFunctionType.PadLeft)); + Visit(EmulateLpadRpad(arguments, node.FunctionType is SqlFunctionType.PadLeft)); return; case SqlFunctionType.Concat: var nod = arguments[0]; @@ -632,7 +632,7 @@ private static SqlDateTimePart ConvertDateTimeOffsetPartToDateTimePart(SqlDateTi }; } - private static SqlCase EmulateLpadOrRpad(IReadOnlyList arguments, bool isLpad) + private static SqlCase EmulateLpadRpad(IReadOnlyList arguments, bool isLpad) { var operand = arguments[0]; var charcount = arguments[1]; From e281961a593fe98d080644ef0871546caa2d8419 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 22 Jan 2025 13:04:41 +0500 Subject: [PATCH 18/23] Improve changelog --- ChangeLog/7.2.0-Beta-2-dev.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog/7.2.0-Beta-2-dev.txt b/ChangeLog/7.2.0-Beta-2-dev.txt index 0e7ff10a24..29d4b11bcb 100644 --- a/ChangeLog/7.2.0-Beta-2-dev.txt +++ b/ChangeLog/7.2.0-Beta-2-dev.txt @@ -1 +1,6 @@ -[main] Upgrade hints change names of constructors' string parameters for better understanding of what suppose to be in them. \ No newline at end of file +[main] Upgrade hints change names of constructors' string parameters for better understanding of what suppose to be in them. +[main] Improved string operations Trim/TrimStart/TrimEnd support +[mysql] SqlDml.NullIf function now correctly translated +[mysql] Improved support for string.PadLeft/PadRight opertaions +[sqlite] Fixed string.Lenght translation +[sqlite] Added support for string.PadLeft/PadRight operations \ No newline at end of file From 79981d1ffb54326b3a5b32cf7e6fcd9853b95741 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 22 Jan 2025 14:54:16 +0500 Subject: [PATCH 19/23] Postgresql: Declare the same setting for nulls in indexes as in order by statement otherwise, index order conflicts with order by which cause longer query execution. According to documentation default settings for nulls are exact opposite. --- .../Sql.Drivers.PostgreSql/v9_0/Translator.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v9_0/Translator.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v9_0/Translator.cs index 22233fd625..cf3954edd8 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v9_0/Translator.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v9_0/Translator.cs @@ -30,6 +30,9 @@ public override void Translate(SqlCompilerContext context, object literalValue) } } + public override void TranslateSortOrder(IOutput output, bool ascending) => + output.Append(ascending ? "ASC NULLS FIRST" : "DESC NULLS LAST"); + // Constructors public Translator(SqlDriver driver) From ee66c74f61b9e9f2de508793f5b2956a4db3b1bc Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Jan 2025 13:06:36 +0500 Subject: [PATCH 20/23] Fix misspelling of "Length" part 2 --- .../Storage/SkippingValidationOnCommitTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs b/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs index ac63ff687a..5ed8ca721a 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/SkippingValidationOnCommitTest.cs @@ -379,7 +379,7 @@ public void FutureConstraintNotImmediateSkippedTest() } [Test] - public void LenghtConstraintImmediateNotSkippedTest() + public void LengthConstraintImmediateNotSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { @@ -415,7 +415,7 @@ public void LenghtConstraintImmediateNotSkippedTest() } [Test] - public void LenghtConstraintImmediateSkippedTest() + public void LengthConstraintImmediateSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { @@ -449,7 +449,7 @@ public void LenghtConstraintImmediateSkippedTest() } [Test] - public void LenghtConstraintNotImmidiateNotSkippedTest() + public void LengthConstraintNotImmidiateNotSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { @@ -485,7 +485,7 @@ public void LenghtConstraintNotImmidiateNotSkippedTest() } [Test] - public void LenghtConstraintNotImmediateSkippedTest() + public void LengthConstraintNotImmediateSkippedTest() { using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { From 06d0f1cb64386c3e4f5bd26de96f30b2b1911a1e Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Jan 2025 13:32:48 +0500 Subject: [PATCH 21/23] Improve changelog --- ChangeLog/7.1.4_dev.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog/7.1.4_dev.txt b/ChangeLog/7.1.4_dev.txt index 754f28c4ee..2c98bef46b 100644 --- a/ChangeLog/7.1.4_dev.txt +++ b/ChangeLog/7.1.4_dev.txt @@ -1,2 +1,3 @@ [main] Addressed IndexOutOfRangeException on translation of certain queries with aggregates -[main] Notification to BuildLog when a hierarchy changes KeyGeneratorKind value to None \ No newline at end of file +[main] Notification to BuildLog when a hierarchy changes KeyGeneratorKind value to None +[postgresql] Added explicit nulls setting for both column order directions to improve OrderBy/OrderByDescending performance \ No newline at end of file From b98643e5a65deac334a7eb2576b2d405d9678e1b Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 24 Jan 2025 18:02:41 +0500 Subject: [PATCH 22/23] Bump version ot 7.1.4 --- ChangeLog/{7.1.4_dev.txt => 7.1.4_Z_Final.txt} | 0 Version.props | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ChangeLog/{7.1.4_dev.txt => 7.1.4_Z_Final.txt} (100%) diff --git a/ChangeLog/7.1.4_dev.txt b/ChangeLog/7.1.4_Z_Final.txt similarity index 100% rename from ChangeLog/7.1.4_dev.txt rename to ChangeLog/7.1.4_Z_Final.txt diff --git a/Version.props b/Version.props index ab29c43318..02b558b9ed 100644 --- a/Version.props +++ b/Version.props @@ -3,7 +3,7 @@ 7.1.4 - dev + From 24fc39f182ef6e7ba584ca9d18f1de610f0bc246 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Mon, 27 Jan 2025 15:52:42 +0500 Subject: [PATCH 23/23] Fix warnings after merge --- Orm/Xtensive.Orm/Orm/Rse/Providers/CompilableProviderVisitor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/Providers/CompilableProviderVisitor.cs b/Orm/Xtensive.Orm/Orm/Rse/Providers/CompilableProviderVisitor.cs index 31dd914c01..ca8f534b05 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Providers/CompilableProviderVisitor.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Providers/CompilableProviderVisitor.cs @@ -152,7 +152,7 @@ protected override CompilableProvider VisitCalculate(CalculateProvider provider) } return !translated && source == provider.Source ? provider - : new CalculateProvider(source, descriptors.ToArray()); + : new CalculateProvider(source, descriptors); } ///