Skip to content

Commit b155848

Browse files
authored
(#210) Fixing UpdatedAt property in sample. (#218)
1 parent 49bd9d1 commit b155848

File tree

6 files changed

+100
-8
lines changed

6 files changed

+100
-8
lines changed

Datasync.Toolkit.sln

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Datasync.C
6060
EndProject
6161
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Datasync.Client.Test", "tests\CommunityToolkit.Datasync.Client.Test\CommunityToolkit.Datasync.Client.Test.csproj", "{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}"
6262
EndProject
63+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{75F709FD-8CC2-4558-A802-FE57086167C2}"
64+
EndProject
65+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Datasync.Server", "samples\datasync-server\src\Sample.Datasync.Server\Sample.Datasync.Server.csproj", "{A9967817-2A2C-4C6D-A133-967A6062E9B3}"
66+
EndProject
6367
Global
6468
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6569
Debug|Any CPU = Debug|Any CPU
@@ -146,6 +150,10 @@ Global
146150
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}.Debug|Any CPU.Build.0 = Debug|Any CPU
147151
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}.Release|Any CPU.ActiveCfg = Release|Any CPU
148152
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}.Release|Any CPU.Build.0 = Release|Any CPU
153+
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
154+
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
155+
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
156+
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Release|Any CPU.Build.0 = Release|Any CPU
149157
EndGlobalSection
150158
GlobalSection(SolutionProperties) = preSolution
151159
HideSolutionNode = FALSE
@@ -171,6 +179,7 @@ Global
171179
{45D47A4E-AD58-40C8-B4CC-95BC888C47A7} = {84AD662A-4B9E-4E64-834D-72529FB7FCE5}
172180
{D3B72031-D4BD-44D3-973C-2752AB1570F6} = {84AD662A-4B9E-4E64-834D-72529FB7FCE5}
173181
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99} = {D59F1489-5D74-4F52-B78B-88037EAB2838}
182+
{A9967817-2A2C-4C6D-A133-967A6062E9B3} = {75F709FD-8CC2-4558-A802-FE57086167C2}
174183
EndGlobalSection
175184
GlobalSection(ExtensibilityGlobals) = postSolution
176185
SolutionGuid = {78A935E9-8F14-448A-BEDF-360FB742F14E}

infra/scripts/write-runsettings.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ $fileContents = @"
1414
<DATASYNC_AZSQL_CONNECTIONSTRING>$($outputs.AZSQL_CONNECTION_STRING)</DATASYNC_AZSQL_CONNECTIONSTRING>
1515
<DATASYNC_COSMOS_CONNECTIONSTRING>$($outputs.COSMOS_CONNECTION_STRING)</DATASYNC_COSMOS_CONNECTIONSTRING>
1616
<DATASYNC_PGSQL_CONNECTIONSTRING>$($outputs.PGSQL_CONNECTION_STRING)</DATASYNC_PGSQL_CONNECTIONSTRING>
17+
<DATASYNC_SERVICE_ENDPOINT>$($outputs.SERVICE_ENDPOINT)</DATASYNC_SERVICE_ENDPOINT>
1718
<ENABLE_SQL_LOGGING>true</ENABLE_SQL_LOGGING>
1819
</EnvironmentVariables>
1920
</RunConfiguration>

samples/datasync-server/src/Sample.Datasync.Server/Db/AppDbContext.cs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,54 @@
33
// See the LICENSE file in the project root for more information.
44

55
using Microsoft.EntityFrameworkCore;
6+
using Microsoft.EntityFrameworkCore.Metadata;
7+
using System.Diagnostics.CodeAnalysis;
68

79
namespace Sample.Datasync.Server.Db;
810

9-
public class AppDbContext : DbContext
11+
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
1012
{
11-
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
12-
{
13-
14-
}
15-
1613
public DbSet<TodoItem> TodoItems => Set<TodoItem>();
1714

1815
public DbSet<TodoList> TodoLists => Set<TodoList>();
1916

2017
public async Task InitializeDatabaseAsync()
2118
{
2219
_ = await Database.EnsureCreatedAsync();
20+
21+
const string datasyncTrigger = @"
22+
CREATE OR ALTER TRIGGER [dbo].[{0}_datasync] ON [dbo].[{0}] AFTER INSERT, UPDATE AS
23+
BEGIN
24+
SET NOCOUNT ON;
25+
UPDATE
26+
[dbo].[{0}]
27+
SET
28+
[UpdatedAt] = SYSUTCDATETIME()
29+
WHERE
30+
[Id] IN (SELECT [Id] FROM INSERTED);
31+
END
32+
"
33+
;
34+
35+
// Install the above trigger to set the UpdatedAt field automatically on insert or update.
36+
foreach (IEntityType table in Model.GetEntityTypes())
37+
{
38+
string sql = string.Format(datasyncTrigger, table.GetTableName());
39+
_ = await Database.ExecuteSqlRawAsync(sql);
40+
}
41+
}
42+
43+
[SuppressMessage("Style", "IDE0058:Expression value is never used", Justification = "Model builder ignores return value.")]
44+
protected override void OnModelCreating(ModelBuilder modelBuilder)
45+
{
46+
// Tells EF Core that the TodoItem entity has a trigger.
47+
modelBuilder.Entity<TodoItem>()
48+
.ToTable(tb => tb.HasTrigger("TodoItem_datasync"));
49+
50+
// Tells EF Core that the TodoList entity has a trigger.
51+
modelBuilder.Entity<TodoList>()
52+
.ToTable(tb => tb.HasTrigger("TodoList_datasync"));
53+
54+
base.OnModelCreating(modelBuilder);
2355
}
2456
}

src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/OperationsQueueManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ internal Dictionary<string, Type> GetEntityMap(OfflineDbContext context)
110110
/// <summary>
111111
/// Retrieves the existing operation that matches an operation for the provided entity.
112112
/// </summary>
113-
/// <param name="entity">The entity being processed.</param>
113+
/// <param name="entityEntry">The entity entry being processed.</param>
114114
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
115115
/// <returns>The operation entity or null if one does not exist.</returns>
116116
/// <exception cref="DatasyncException">Thrown if the entity ID of the provided entity is invalid.</exception>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Net;
6+
using System.Net.Http.Json;
7+
8+
namespace CommunityToolkit.Datasync.Client.Test.Live;
9+
10+
[ExcludeFromCodeCoverage]
11+
public class SampleServerTests
12+
{
13+
private readonly bool liveTestsAreEnabled = Environment.GetEnvironmentVariable("DATASYNC_SERVICE_ENDPOINT") is not null;
14+
private readonly string serviceEndpoint = Environment.GetEnvironmentVariable("DATASYNC_SERVICE_ENDPOINT");
15+
16+
[SkippableFact]
17+
public async Task Metadata_GetsSetByServer()
18+
{
19+
Skip.IfNot(this.liveTestsAreEnabled);
20+
21+
DateTimeOffset now = DateTimeOffset.UtcNow;
22+
HttpClient client = new();
23+
TodoItem source = new() { Title = "Test item" };
24+
HttpResponseMessage response = await client.PostAsJsonAsync($"{this.serviceEndpoint}/tables/TodoItem", source);
25+
26+
response.Should().HaveHttpStatusCode(HttpStatusCode.Created);
27+
28+
TodoItem result = await response.Content.ReadFromJsonAsync<TodoItem>();
29+
result.Id.Should().NotBeNullOrEmpty();
30+
result.UpdatedAt.Should().NotBeNull().And.BeAfter(now);
31+
result.Version.Should().NotBeNullOrEmpty();
32+
result.Deleted.Should().BeFalse();
33+
result.Title.Should().Be("Test item");
34+
result.IsComplete.Should().BeFalse();
35+
36+
response.Headers.Location.Should().NotBeNull().And.BeEquivalentTo(new Uri($"{this.serviceEndpoint}/tables/TodoItem/{result.Id}"));
37+
response.Headers.ETag.ToString().Should().Be($"\"{result.Version}\"");
38+
}
39+
40+
// This must match the TodoItem class in the server project.
41+
public class TodoItem
42+
{
43+
public string Id { get; set; }
44+
public DateTimeOffset? UpdatedAt { get; set; }
45+
public string Version { get; set; }
46+
public bool Deleted { get; set; }
47+
public string Title { get; set; }
48+
public bool IsComplete { get; set; }
49+
}
50+
}

tests/CommunityToolkit.Datasync.TestCommon/Databases/AzureSql/AzureSqlDbContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal void InitializeDatabase(bool clearEntities)
3737
UPDATE
3838
[dbo].[{0}]
3939
SET
40-
[UpdatedAt] = GETUTCDATE()
40+
[UpdatedAt] = SYSUTCDATETIME()
4141
WHERE
4242
[Id] IN (SELECT [Id] FROM INSERTED);
4343
END

0 commit comments

Comments
 (0)