Skip to content

Commit e5ace3c

Browse files
committed
fix merge bug
1 parent 153368d commit e5ace3c

9 files changed

+278
-12
lines changed

src/FluentCommand.SqlServer/Merge/DataMergeDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public static void AutoMap<TEntity>(DataMergeDefinition mergeDefinition)
121121

122122
foreach (var property in typeAccessor.GetProperties())
123123
{
124-
string sourceColumn = property.Name;
124+
string sourceColumn = property.Column;
125125
string targetColumn = property.Column;
126126
string nativeType = property.ColumnType ?? SqlTypeMapping.NativeType(property.MemberType);
127127

src/FluentCommand.SqlServer/Merge/DataMergeGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ private static void AppendUsingData(DataMergeDefinition mergeDefinition, List<Da
178178
builder
179179
.AppendLineIf(", ", s => wroteRow)
180180
.Append(' ', TabSize)
181-
.Append("(");
181+
.Append("(");
182182

183183
for (int i = 0; i < reader.FieldCount; i++)
184184
{

test/FluentCommand.Entities/Member.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.ComponentModel.DataAnnotations.Schema;
2+
3+
namespace FluentCommand.Entities;
4+
5+
[Table("member_user", Schema = "dbo")]
6+
public class Member
7+
{
8+
[Column("Id")]
9+
public Guid Id { get; set; }
10+
11+
[Column("email_address")]
12+
public string EmailAddress { get; set; }
13+
14+
[Column("display_name")]
15+
public string DisplayName { get; set; }
16+
17+
[Column("first_name")]
18+
public string FirstName { get; set; }
19+
20+
[Column("last_name")]
21+
public string LastName { get; set; }
22+
}

test/FluentCommand.SqlServer.Tests/DataMergeGeneratorTests.cs

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void QuoteIdentifier()
6161
}
6262

6363
[Fact]
64-
public void BuildMergeTests()
64+
public async System.Threading.Tasks.Task BuildMergeTests()
6565
{
6666
var definition = new DataMergeDefinition();
6767

@@ -79,13 +79,15 @@ public void BuildMergeTests()
7979
var sql = DataMergeGenerator.BuildMerge(definition);
8080
sql.Should().NotBeNullOrEmpty();
8181

82-
Output.WriteLine("MergeStatement:");
83-
Output.WriteLine(sql);
82+
await Verifier
83+
.Verify(sql)
84+
.UseDirectory("Snapshots")
85+
.AddScrubber(scrubber => scrubber.Replace(definition.TemporaryTable, "#MergeTable"));
8486
}
8587

8688

8789
[Fact]
88-
public void BuildMergeDataTests()
90+
public async System.Threading.Tasks.Task BuildMergeDataTests()
8991
{
9092
var definition = new DataMergeDefinition();
9193

@@ -123,8 +125,9 @@ public void BuildMergeDataTests()
123125
var sql = DataMergeGenerator.BuildMerge(definition, listDataReader);
124126
sql.Should().NotBeNullOrEmpty();
125127

126-
Output.WriteLine("MergeStatement:");
127-
Output.WriteLine(sql);
128+
await Verifier
129+
.Verify(sql)
130+
.UseDirectory("Snapshots");
128131
}
129132

130133
[Fact]
@@ -248,7 +251,7 @@ await Verifier
248251
}
249252

250253
[Fact]
251-
public void BuildMergeDataOutputTests()
254+
public async System.Threading.Tasks.Task BuildMergeDataOutputTests()
252255
{
253256
var definition = new DataMergeDefinition();
254257

@@ -282,7 +285,7 @@ public void BuildMergeDataOutputTests()
282285
},
283286
new UserImport
284287
{
285-
EmailAddress = $"random.{DateTime.Now.Ticks}@email.com",
288+
EmailAddress = $"random@email.com",
286289
DisplayName = "Random User",
287290
FirstName = "Random",
288291
LastName = "User"
@@ -294,8 +297,57 @@ public void BuildMergeDataOutputTests()
294297
var sql = DataMergeGenerator.BuildMerge(definition, dataTable);
295298
sql.Should().NotBeNullOrEmpty();
296299

297-
Output.WriteLine("MergeStatement:");
298-
Output.WriteLine(sql);
300+
await Verifier
301+
.Verify(sql)
302+
.UseDirectory("Snapshots");
299303
}
300304

305+
[Fact]
306+
public async System.Threading.Tasks.Task BuildMergeDataMismatchTests()
307+
{
308+
var definition = new DataMergeDefinition();
309+
310+
DataMergeDefinition.AutoMap<Member>(definition);
311+
definition.Columns.Should().NotBeNullOrEmpty();
312+
313+
var column = definition.Columns.Find(c => c.SourceColumn == "email_address");
314+
column.Should().NotBeNull();
315+
316+
column.IsKey = true;
317+
column.CanUpdate = false;
318+
319+
var users = new List<Member>
320+
{
321+
new Member
322+
{
323+
EmailAddress = "test@email.com",
324+
DisplayName = "Test User",
325+
FirstName = "Test",
326+
LastName = "User"
327+
},
328+
new Member
329+
{
330+
EmailAddress = "blah@email.com",
331+
DisplayName = "Blah User",
332+
FirstName = "Blah",
333+
LastName = "User"
334+
},
335+
new Member
336+
{
337+
EmailAddress = $"random@email.com",
338+
DisplayName = "Random User",
339+
FirstName = "Random",
340+
LastName = "User"
341+
}
342+
};
343+
344+
var dataTable = new ListDataReader<Member>(users);
345+
346+
var mergeDataStatement = DataMergeGenerator.BuildMerge(definition, dataTable);
347+
mergeDataStatement.Should().NotBeNullOrEmpty();
348+
349+
await Verifier
350+
.Verify(mergeDataStatement)
351+
.UseDirectory("Snapshots");
352+
}
301353
}

test/FluentCommand.SqlServer.Tests/Scripts/Script001.Tracker.Schema.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ CREATE TABLE [dbo].[User] (
115115
CONSTRAINT [PK_User] PRIMARY KEY ([Id])
116116
);
117117

118+
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[member_user]') AND type in (N'U'))
119+
CREATE TABLE [dbo].[member_user] (
120+
[Id] uniqueidentifier NOT NULL DEFAULT (NEWSEQUENTIALID()),
121+
[email_address] nvarchar(256) NOT NULL,
122+
[display_name] nvarchar(256) NOT NULL,
123+
[first_name] nvarchar(256) NULL,
124+
[last_name] nvarchar(256) NULL,
125+
CONSTRAINT [PK_member_user] PRIMARY KEY ([Id])
126+
);
127+
118128
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UserLogin]') AND type in (N'U'))
119129
CREATE TABLE [dbo].[UserLogin] (
120130
[Id] uniqueidentifier NOT NULL DEFAULT (NEWSEQUENTIALID()),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
MERGE INTO [dbo].[member_user] AS t
2+
USING
3+
(
4+
VALUES
5+
('00000000-0000-0000-0000-000000000000', 'test@email.com', 'Test User', 'Test', 'User'),
6+
('00000000-0000-0000-0000-000000000000', 'blah@email.com', 'Blah User', 'Blah', 'User'),
7+
('00000000-0000-0000-0000-000000000000', 'random@email.com', 'Random User', 'Random', 'User')
8+
)
9+
AS s
10+
(
11+
[Id], [email_address], [display_name], [first_name], [last_name]
12+
)
13+
ON
14+
(
15+
t.[email_address] = s.[email_address]
16+
)
17+
WHEN NOT MATCHED BY TARGET THEN
18+
INSERT
19+
(
20+
[Id],
21+
[email_address],
22+
[display_name],
23+
[first_name],
24+
[last_name]
25+
)
26+
VALUES
27+
(
28+
s.[Id],
29+
s.[email_address],
30+
s.[display_name],
31+
s.[first_name],
32+
s.[last_name]
33+
)
34+
WHEN MATCHED THEN
35+
UPDATE SET
36+
t.[Id] = s.[Id],
37+
t.[display_name] = s.[display_name],
38+
t.[first_name] = s.[first_name],
39+
t.[last_name] = s.[last_name]
40+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
MERGE INTO [dbo].[User] AS t
2+
USING
3+
(
4+
VALUES
5+
('test@email.com', 'Test User', 'Test', 'User', NULL, NULL),
6+
('blah@email.com', 'Blah User', 'Blah', 'User', NULL, NULL),
7+
('random@email.com', 'Random User', 'Random', 'User', NULL, NULL)
8+
)
9+
AS s
10+
(
11+
[EmailAddress], [DisplayName], [FirstName], [LastName], [LockoutEnd], [LastLogin]
12+
)
13+
ON
14+
(
15+
t.[EmailAddress] = s.[EmailAddress]
16+
)
17+
WHEN NOT MATCHED BY TARGET THEN
18+
INSERT
19+
(
20+
[EmailAddress],
21+
[DisplayName],
22+
[FirstName],
23+
[LastName],
24+
[LockoutEnd],
25+
[LastLogin]
26+
)
27+
VALUES
28+
(
29+
s.[EmailAddress],
30+
s.[DisplayName],
31+
s.[FirstName],
32+
s.[LastName],
33+
s.[LockoutEnd],
34+
s.[LastLogin]
35+
)
36+
WHEN MATCHED THEN
37+
UPDATE SET
38+
t.[DisplayName] = s.[DisplayName],
39+
t.[FirstName] = s.[FirstName],
40+
t.[LastName] = s.[LastName],
41+
t.[LockoutEnd] = s.[LockoutEnd],
42+
t.[LastLogin] = s.[LastLogin]
43+
OUTPUT
44+
$action as [Action],
45+
DELETED.[EmailAddress] as [OriginalEmailAddress],
46+
INSERTED.[EmailAddress] as [CurrentEmailAddress],
47+
DELETED.[DisplayName] as [OriginalDisplayName],
48+
INSERTED.[DisplayName] as [CurrentDisplayName],
49+
DELETED.[FirstName] as [OriginalFirstName],
50+
INSERTED.[FirstName] as [CurrentFirstName],
51+
DELETED.[LastName] as [OriginalLastName],
52+
INSERTED.[LastName] as [CurrentLastName],
53+
DELETED.[LockoutEnd] as [OriginalLockoutEnd],
54+
INSERTED.[LockoutEnd] as [CurrentLockoutEnd],
55+
DELETED.[LastLogin] as [OriginalLastLogin],
56+
INSERTED.[LastLogin] as [CurrentLastLogin];
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
MERGE INTO [dbo].[User] AS t
2+
USING
3+
(
4+
VALUES
5+
('test@email.com', 'Test User', 'Test', 'User', NULL, NULL),
6+
('blah@email.com', 'Blah User', 'Blah', 'User', NULL, NULL)
7+
)
8+
AS s
9+
(
10+
[EmailAddress], [DisplayName], [FirstName], [LastName], [LockoutEnd], [LastLogin]
11+
)
12+
ON
13+
(
14+
t.[EmailAddress] = s.[EmailAddress]
15+
)
16+
WHEN NOT MATCHED BY TARGET THEN
17+
INSERT
18+
(
19+
[EmailAddress],
20+
[DisplayName],
21+
[FirstName],
22+
[LastName],
23+
[LockoutEnd],
24+
[LastLogin]
25+
)
26+
VALUES
27+
(
28+
s.[EmailAddress],
29+
s.[DisplayName],
30+
s.[FirstName],
31+
s.[LastName],
32+
s.[LockoutEnd],
33+
s.[LastLogin]
34+
)
35+
WHEN MATCHED THEN
36+
UPDATE SET
37+
t.[DisplayName] = s.[DisplayName],
38+
t.[FirstName] = s.[FirstName],
39+
t.[LastName] = s.[LastName],
40+
t.[LockoutEnd] = s.[LockoutEnd],
41+
t.[LastLogin] = s.[LastLogin]
42+
;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
MERGE INTO [dbo].[User] AS t
2+
USING
3+
(
4+
SELECT
5+
[EmailAddress],
6+
[DisplayName],
7+
[FirstName],
8+
[LastName],
9+
[LockoutEnd],
10+
[LastLogin]
11+
FROM [#MergeTable]
12+
)
13+
AS s
14+
ON
15+
(
16+
t.[EmailAddress] = s.[EmailAddress]
17+
)
18+
WHEN NOT MATCHED BY TARGET THEN
19+
INSERT
20+
(
21+
[EmailAddress],
22+
[DisplayName],
23+
[FirstName],
24+
[LastName],
25+
[LockoutEnd],
26+
[LastLogin]
27+
)
28+
VALUES
29+
(
30+
s.[EmailAddress],
31+
s.[DisplayName],
32+
s.[FirstName],
33+
s.[LastName],
34+
s.[LockoutEnd],
35+
s.[LastLogin]
36+
)
37+
WHEN MATCHED THEN
38+
UPDATE SET
39+
t.[DisplayName] = s.[DisplayName],
40+
t.[FirstName] = s.[FirstName],
41+
t.[LastName] = s.[LastName],
42+
t.[LockoutEnd] = s.[LockoutEnd],
43+
t.[LastLogin] = s.[LastLogin]
44+
;

0 commit comments

Comments
 (0)