Skip to content

Commit 09ee787

Browse files
committed
Merge branch 'master' into sqlcompiler-code-improvements
# Conflicts: # Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs
2 parents c461f6c + 5ae4635 commit 09ee787

33 files changed

+2151
-765
lines changed

Extensions/Xtensive.Orm.BulkOperations.Tests/Other.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
using System;
1+
// Copyright (C) 2012-2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
// Created by: Alexander Ovchinnikov
5+
// Created: 2012.02.29
6+
7+
using System;
28
using System.Collections.Generic;
39
using System.Linq;
410
using NUnit.Framework;
@@ -242,5 +248,34 @@ public void In()
242248
trx.Complete();
243249
}
244250
}
251+
252+
[Test]
253+
public void InWithCombinationWithFieldUsageUpdate()
254+
{
255+
using (Session session = Domain.OpenSession())
256+
using (TransactionScope trx = session.OpenTransaction()) {
257+
var idsToUpdate = new[] { 99, 100, 102 };
258+
var prefix = "abc";
259+
260+
var bar1 = new Bar(session, 100) { Name = "test1", Count = 3 };
261+
var bar2 = new Bar(session, 101) { Name = "test2", Count = 4 };
262+
var bar3 = new Bar(session, 102) { Name = "test3", Count = 5 };
263+
session.SaveChanges();
264+
265+
var updatedCount = session.Query.All<Bar>()
266+
.Where(b => b.Id.In(IncludeAlgorithm.ComplexCondition, idsToUpdate))
267+
.Update(bar => new Bar(session) { Name = prefix + bar.Name });
268+
Assert.That(updatedCount, Is.EqualTo(2));
269+
270+
var all = session.Query.All<Bar>().Where(b=> b.Id == 100 || b.Id == 101 || b.Id == 102).ToList();
271+
var updatedEntities = all.Where(b => b.Id.In(idsToUpdate));
272+
Assert.That(updatedEntities.All(e => e.Name.StartsWith(prefix)), Is.True);
273+
274+
var leftEntities = all.Where(b => !b.Id.In(idsToUpdate));
275+
Assert.That(leftEntities.All(e => e.Name.StartsWith(prefix)), Is.False);
276+
277+
trx.Complete();
278+
}
279+
}
245280
}
246281
}

Orm.sln

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xtensive.Orm.Security.Tests
6565
EndProject
6666
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xtensive.Orm.Tracking.Tests", "Extensions\Xtensive.Orm.Tracking.Tests\Xtensive.Orm.Tracking.Tests.csproj", "{15CC7358-3A5B-4146-A5CB-78DAE75E88E6}"
6767
EndProject
68-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DA490A4E-F9D1-474B-82C5-A1C5930F3C91}"
68+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Cfg", ".Cfg", "{C02BF3D5-F591-454D-81D4-A3135A24FB81}"
6969
ProjectSection(SolutionItems) = preProject
7070
.editorconfig = .editorconfig
71+
.gitignore = .gitignore
7172
Directory.Build.props = Directory.Build.props
7273
Version.props = Version.props
7374
EndProjectSection

Orm/Xtensive.Orm.Tests/Issues/CustomCompilerException.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2011 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2011-2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Alexis Kochetov
55
// Created: 2011.05.29
66

Orm/Xtensive.Orm.Tests/Issues/IssueJira0346_OptimizeSessionSaveChangesWithoutInboundOnlyAndOutboundOnly.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2013 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2013-2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Alexey Kulakov
55
// Created: 2013.07.30
66

Orm/Xtensive.Orm.Tests/Issues/IssueJira0617_IncorrectRemoveOfRedundantColumns.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2015 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2015-2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Alexey Kulakov
55
// Created: 2015.12.01
66

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (C) 2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
// Created by: Alexey Kulakov
5+
// Created: 2020.02.14
6+
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Text;
10+
using NUnit.Framework;
11+
using Xtensive.Orm.Configuration;
12+
using Xtensive.Orm.Validation;
13+
using Xtensive.Orm.Tests.Issues.IssueJira0792_UnableToRemoveAssignedEntityWithNonNullableAssociationFieldModel;
14+
15+
namespace Xtensive.Orm.Tests.Issues.IssueJira0792_UnableToRemoveAssignedEntityWithNonNullableAssociationFieldModel
16+
{
17+
[HierarchyRoot]
18+
public class Job : Entity
19+
{
20+
[Field, Key]
21+
public long Id { get; private set; }
22+
23+
[Field]
24+
[Association(PairTo = nameof (JobTechnology.ReqiredJob),
25+
OnTargetRemove = OnRemoveAction.Clear,
26+
OnOwnerRemove = OnRemoveAction.Cascade)]
27+
public JobTechnology Technology { get; set; }
28+
29+
public Job(Session session)
30+
: base(session)
31+
{
32+
}
33+
}
34+
35+
[HierarchyRoot]
36+
public class JobTechnology : Entity
37+
{
38+
[Field, Key]
39+
public long Id { get; set; }
40+
41+
[Field(Nullable = false), NotNullConstraint]
42+
public Job ReqiredJob { get; set; }
43+
44+
public JobTechnology(Session session, Job job)
45+
: base(session)
46+
{
47+
ReqiredJob = job;
48+
}
49+
}
50+
}
51+
52+
namespace Xtensive.Orm.Tests.Issues
53+
{
54+
public class IssueJira0792_UnableToRemoveAssignedEntityWithNonNullableAssociationField : AutoBuildTest
55+
{
56+
protected override DomainConfiguration BuildConfiguration()
57+
{
58+
var configuration = base.BuildConfiguration();
59+
configuration.Types.Register(typeof(Job).Assembly, typeof(Job).Namespace);
60+
configuration.UpgradeMode = DomainUpgradeMode.Recreate;
61+
return configuration;
62+
}
63+
64+
protected override void PopulateData()
65+
{
66+
using (var session = Domain.OpenSession())
67+
using (var transaction = session.OpenTransaction()) {
68+
new JobTechnology(session, new Job(session));
69+
new JobTechnology(session, new Job(session));
70+
new JobTechnology(session, new Job(session));
71+
new JobTechnology(session, new Job(session));
72+
73+
transaction.Complete();
74+
}
75+
}
76+
77+
[Test]
78+
public void MainTest()
79+
{
80+
using (var session = Domain.OpenSession())
81+
using (var transaction = session.OpenTransaction()) {
82+
foreach (var job in session.Query.All<Job>()) {
83+
job.Technology.Remove();
84+
session.SaveChanges();
85+
}
86+
}
87+
}
88+
}
89+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
// Copyright (C) 2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
// Created by: Alexey Kulakov
5+
// Created: 2020.02.18
6+
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Text;
10+
using Xtensive.Orm.Configuration;
11+
using Xtensive.Orm.Validation;
12+
using Xtensive.Orm.Tests.Issues.IssueJira0793_FieldValidationTriggersLazyLoadFieldsFetchModel;
13+
using NUnit.Framework;
14+
using Xtensive.Core;
15+
16+
namespace Xtensive.Orm.Tests.Issues.IssueJira0793_FieldValidationTriggersLazyLoadFieldsFetchModel
17+
{
18+
[HierarchyRoot]
19+
public class Book : Entity
20+
{
21+
[Field, Key]
22+
public int Id { get; set; }
23+
24+
[Field(Length = 50), NotNullOrEmptyConstraint]
25+
public string Title { get; set; }
26+
27+
[Field(Length = int.MaxValue, LazyLoad = true)]
28+
public string Description { get; set; }
29+
30+
[Field(LazyLoad = true)]
31+
public byte[] BookFile { get; set; }
32+
33+
[Field(Length = 5)]
34+
public string FileExtension { get; set; }
35+
36+
[Field]
37+
public Author Author { get; set; }
38+
}
39+
40+
[HierarchyRoot]
41+
public class Author : Entity
42+
{
43+
[Field, Key]
44+
public int Id { get; set; }
45+
46+
[Field()]
47+
public string FirstName { get; set; }
48+
49+
[Field]
50+
public string LastName { get; set; }
51+
52+
[Field(Length = int.MaxValue, LazyLoad = true)]
53+
[NotNullConstraint]// should always be triggered
54+
public string Biography { get; set; }
55+
}
56+
57+
[HierarchyRoot]
58+
public class Chapter : Entity
59+
{
60+
[Field, Key]
61+
public int Id { get; set; }
62+
63+
[Field]
64+
public Book Owner { get; set; }
65+
66+
[Field]
67+
public string Title { get; set; }
68+
69+
[Field(Length = int.MaxValue, LazyLoad = true)]
70+
[NotNullOrEmptyConstraint(ValidateOnlyIfModified = true)]// should validate only if changed
71+
public string Description { get; set; }
72+
}
73+
74+
public class QueryCounter
75+
{
76+
public int Count { get; private set; }
77+
78+
public Disposable Attach(Session session)
79+
{
80+
session.Events.DbCommandExecuted += Encount;
81+
return new Disposable((disposing) => session.Events.DbCommandExecuted -= Encount);
82+
}
83+
84+
public void Reset() => Count = 0;
85+
86+
private void Encount(object sender, DbCommandEventArgs eventArgs) => Count++;
87+
88+
public QueryCounter()
89+
{
90+
Count = 0;
91+
}
92+
}
93+
}
94+
95+
namespace Xtensive.Orm.Tests.Issues
96+
{
97+
public class IssueJira0793_FieldValidationTriggersLazyLoadFieldsFetch : AutoBuildTest
98+
{
99+
private Key oblomovKey;
100+
private Key goncharovKey;
101+
102+
protected override DomainConfiguration BuildConfiguration()
103+
{
104+
var configuration = base.BuildConfiguration();
105+
configuration.Types.Register(typeof(Book).Assembly, typeof(Book).Namespace);
106+
configuration.UpgradeMode = DomainUpgradeMode.Recreate;
107+
return configuration;
108+
}
109+
110+
protected override void PopulateData()
111+
{
112+
using (var session = Domain.OpenSession())
113+
using (var transaction = session.OpenTransaction()) {
114+
var author = new Author() {
115+
FirstName = "Ivan",
116+
LastName = "Goncharov",
117+
Biography = "Some biography of Ivan Alexandrovich" };
118+
var book = new Book() {
119+
Title = "Oblomov",
120+
Description = "A drama about how human's lazyness and absence of strenght may affect his life.",
121+
BookFile = new byte[] { 3, 3, 3, 3, 3, 3, 3 },
122+
Author = author
123+
};
124+
125+
new Chapter() { Title = "Chapter #1", Description = "Detailed description of Chapter #1", Owner = book };
126+
new Chapter() { Title = "Chapter #2", Description = "Detailed description of Chapter #2", Owner = book };
127+
new Chapter() { Title = "Chapter #3", Description = "Detailed description of Chapter #3", Owner = book };
128+
129+
oblomovKey = book.Key;
130+
goncharovKey = author.Key;
131+
132+
transaction.Complete();
133+
}
134+
}
135+
136+
[Test]
137+
public void LazyFieldHasNoConstraintTest()
138+
{
139+
var counter = new QueryCounter();
140+
using (var session = Domain.OpenSession()) {
141+
using (counter.Attach(session))
142+
using (var transaction = session.OpenTransaction()) {
143+
var oblomov = session.Query.Single<Book>(oblomovKey);
144+
oblomov.Title = "Oblomov by Goncharov";
145+
transaction.Complete();
146+
}
147+
Assert.That(counter.Count, Is.EqualTo(2));
148+
counter.Reset();
149+
}
150+
}
151+
152+
[Test]
153+
public void LazyFieldHasCheckAlwaysConstraintTest()
154+
{
155+
var counter = new QueryCounter();
156+
using (var session = Domain.OpenSession()) {
157+
using (counter.Attach(session))
158+
using (var transaction = session.OpenTransaction()) {
159+
var goncharov = session.Query.Single<Author>(goncharovKey);
160+
goncharov.FirstName = goncharov.FirstName + "modified"; // should prefetch lazy load field
161+
transaction.Complete();
162+
}
163+
Assert.That(counter.Count, Is.EqualTo(3));
164+
counter.Reset();
165+
}
166+
}
167+
168+
[Test]
169+
public void LazyFieldHasCheckIfModifiedConstraintTest()
170+
{
171+
var counter = new QueryCounter();
172+
using (var session = Domain.OpenSession()) {
173+
using (counter.Attach(session))
174+
using (var transaction = session.OpenTransaction()) {
175+
foreach (var chapter in session.Query.All<Chapter>()) {
176+
chapter.Title = chapter.Title + " modified";
177+
}
178+
transaction.Complete();
179+
}
180+
Assert.That(counter.Count, Is.EqualTo(2));
181+
counter.Reset();
182+
}
183+
184+
using (var session = Domain.OpenSession()) {
185+
int updatedItems = 0;
186+
using (counter.Attach(session))
187+
using (var transaction = session.OpenTransaction()) {
188+
foreach(var chapter in session.Query.All<Chapter>()) {
189+
chapter.Description = chapter.Description + " modified";
190+
updatedItems++;
191+
}
192+
transaction.Complete();
193+
}
194+
Assert.That(counter.Count, Is.EqualTo(5)); // query + fetches + update
195+
counter.Reset();
196+
}
197+
}
198+
}
199+
}

0 commit comments

Comments
 (0)