Skip to content

Commit b90e97d

Browse files
authored
Merge pull request #90 from DataObjects-NET/bulk-operations-via-in-bug
Addresses wrong table alias assignment issue for Bulk Update and Bulk Delete
2 parents 738ace3 + a3e9ee1 commit b90e97d

File tree

3 files changed

+202
-112
lines changed

3 files changed

+202
-112
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using NUnit.Framework;
6+
using TestCommon.Model;
7+
using Xtensive.Orm.BulkOperations.Tests.Issues.WrongAliassesIssue;
8+
using Xtensive.Sql;
9+
10+
namespace Xtensive.Orm.BulkOperations.Tests.Issues
11+
{
12+
public class JoinedTableAsSourceForOperationsCauseWrongAliases : AutoBuildTest
13+
{
14+
[Test]
15+
public void CustomerCase()
16+
{
17+
using (var session = Domain.OpenSession())
18+
using (var tx = session.OpenTransaction()) {
19+
var query = session.Query.All<DowntimeReason>()
20+
.Where(r => r.DowntimeInfo.Record.Equipment.Id == 333);
21+
22+
var queryResult = query.Delete();
23+
}
24+
}
25+
26+
[Test]
27+
public void MultipleKeyTest()
28+
{
29+
using (var session = Domain.OpenSession())
30+
using (var tx = session.OpenTransaction()) {
31+
var query = session.Query.All<DowntimeReason2>()
32+
.Where(r => r.DowntimeInfo.Record.Equipment.Id == 333);
33+
34+
var queryResult = query.Delete();
35+
}
36+
}
37+
}
38+
}
39+
40+
namespace Xtensive.Orm.BulkOperations.Tests.Issues.WrongAliassesIssue
41+
{
42+
[HierarchyRoot]
43+
public class DowntimeReason : Entity
44+
{
45+
[Field, Key]
46+
public int Id { get; private set; }
47+
48+
[Field]
49+
public DowntimeInfo DowntimeInfo { get; set; }
50+
}
51+
52+
[HierarchyRoot]
53+
[KeyGenerator(KeyGeneratorKind.None)]
54+
public class DowntimeReason2 : Entity
55+
{
56+
[Field, Key(0)]
57+
public int Id { get; private set; }
58+
59+
[Field, Key(1)]
60+
public int Id2 { get; private set; }
61+
62+
[Field]
63+
public DowntimeInfo DowntimeInfo { get; set; }
64+
}
65+
66+
[HierarchyRoot]
67+
public class DowntimeInfo : Entity
68+
{
69+
[Field, Key]
70+
public int Id { get; private set; }
71+
72+
[Field]
73+
public Record Record { get; set; }
74+
}
75+
76+
[HierarchyRoot]
77+
public class Record : Entity
78+
{
79+
[Field, Key]
80+
public int Id { get; private set; }
81+
82+
[Field]
83+
public Equipment Equipment { get; set; }
84+
}
85+
86+
[HierarchyRoot]
87+
public class Equipment : Entity
88+
{
89+
[Field, Key]
90+
public int Id { get; private set; }
91+
}
92+
}

Extensions/Xtensive.Orm.BulkOperations/Internals/Operation.cs

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@
44

55
using System;
66
using System.Collections.Generic;
7-
using System.Data.Common;
87
using System.Linq;
98
using System.Reflection;
109
using Xtensive.Core;
1110
using Xtensive.Orm.Linq;
12-
using Xtensive.Orm.Model;
1311
using Xtensive.Orm.Providers;
1412
using Xtensive.Orm.Services;
15-
using Xtensive.Sql.Model;
1613
using Xtensive.Sql;
1714
using Xtensive.Sql.Dml;
1815
using QueryParameterBinding = Xtensive.Orm.Services.QueryParameterBinding;
@@ -24,21 +21,24 @@ internal abstract class Operation<T>
2421
where T : class, IEntity
2522
{
2623
private static readonly MethodInfo TranslateQueryMethod = typeof(QueryBuilder).GetMethod("TranslateQuery");
24+
2725
public readonly QueryProvider QueryProvider;
26+
public readonly QueryBuilder QueryBuilder;
2827
public List<QueryParameterBinding> Bindings;
29-
protected DomainHandler DomainHandler;
30-
protected PrimaryIndexMapping[] PrimaryIndexes;
31-
public QueryBuilder QueryBuilder;
32-
public Session Session;
33-
protected TypeInfo TypeInfo;
3428
public SqlTableRef JoinedTableRef;
3529

30+
protected readonly DomainHandler DomainHandler;
31+
protected readonly PrimaryIndexMapping[] PrimaryIndexes;
32+
protected readonly TypeInfo TypeInfo;
33+
34+
public Session Session { get { return QueryBuilder.Session; } }
35+
3636
public int Execute()
3737
{
3838
EnsureTransactionIsStarted();
39-
QueryProvider.Session.SaveChanges();
39+
Session.SaveChanges();
4040
int value = ExecuteInternal();
41-
SessionStateAccessor accessor = DirectStateAccessor.Get(QueryProvider.Session);
41+
var accessor = DirectStateAccessor.Get(Session);
4242
accessor.Invalidate();
4343
return value;
4444
}
@@ -49,45 +49,36 @@ protected void EnsureTransactionIsStarted()
4949
{
5050
var accessor = QueryProvider.Session.Services.Demand<DirectSqlAccessor>();
5151
#pragma warning disable 168
52-
DbTransaction notUsed = accessor.Transaction;
52+
var notUsed = accessor.Transaction;
5353
#pragma warning restore 168
5454
}
5555

5656
protected abstract int ExecuteInternal();
5757

58-
public QueryTranslationResult GetRequest(IQueryable<T> query)
59-
{
60-
return QueryBuilder.TranslateQuery(query);
61-
}
58+
public QueryTranslationResult GetRequest(IQueryable<T> query) => QueryBuilder.TranslateQuery(query);
6259

63-
public QueryTranslationResult GetRequest(Type type, IQueryable query)
64-
{
65-
return
66-
(QueryTranslationResult) TranslateQueryMethod.MakeGenericMethod(type).Invoke(QueryBuilder, new object[] {query});
67-
}
60+
public QueryTranslationResult GetRequest(Type type, IQueryable query) =>
61+
(QueryTranslationResult) TranslateQueryMethod.MakeGenericMethod(type).Invoke(QueryBuilder, new object[] { query });
6862

69-
public TypeInfo GetTypeInfo(Type entityType)
70-
{
71-
return Session.Domain.Model.Hierarchies.SelectMany(a => a.Types).Single(a => a.UnderlyingType==entityType);
72-
}
63+
public TypeInfo GetTypeInfo(Type entityType) =>
64+
Session.Domain.Model.Hierarchies.SelectMany(a => a.Types).Single(a => a.UnderlyingType == entityType);
7365

7466
#endregion
7567

7668
protected Operation(QueryProvider queryProvider)
7769
{
7870
QueryProvider = queryProvider;
79-
Type entityType = typeof (T);
80-
Session = queryProvider.Session;
81-
DomainHandler = Session.Domain.Services.Get<DomainHandler>();
82-
TypeInfo =
83-
queryProvider.Session.Domain.Model.Hierarchies.SelectMany(a => a.Types).Single(
84-
a => a.UnderlyingType==entityType);
85-
var mapping = Session.StorageNode.Mapping;
71+
var entityType = typeof(T);
72+
var session = queryProvider.Session;
73+
DomainHandler = session.Domain.Services.Get<DomainHandler>();
74+
TypeInfo = DomainHandler.Domain.Model.Hierarchies.SelectMany(a => a.Types)
75+
.Single(a => a.UnderlyingType == entityType);
76+
var mapping = session.StorageNode.Mapping;
8677
PrimaryIndexes = TypeInfo.AffectedIndexes
8778
.Where(i => i.IsPrimary)
8879
.Select(i => new PrimaryIndexMapping(i, mapping[i.ReflectedType]))
8980
.ToArray();
90-
QueryBuilder = Session.Services.Get<QueryBuilder>();
81+
QueryBuilder = session.Services.Get<QueryBuilder>();
9182
}
9283

9384
protected QueryCommand ToCommand(SqlStatement statement)

0 commit comments

Comments
 (0)