Skip to content

Commit

Permalink
(#210) Fixing UpdatedAt property in sample. (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianhall authored Jan 21, 2025
1 parent 49bd9d1 commit b155848
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 8 deletions.
9 changes: 9 additions & 0 deletions Datasync.Toolkit.sln
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Datasync.C
EndProject
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}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{75F709FD-8CC2-4558-A802-FE57086167C2}"
EndProject
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}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -146,6 +150,10 @@ Global
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99}.Release|Any CPU.Build.0 = Release|Any CPU
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9967817-2A2C-4C6D-A133-967A6062E9B3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -171,6 +179,7 @@ Global
{45D47A4E-AD58-40C8-B4CC-95BC888C47A7} = {84AD662A-4B9E-4E64-834D-72529FB7FCE5}
{D3B72031-D4BD-44D3-973C-2752AB1570F6} = {84AD662A-4B9E-4E64-834D-72529FB7FCE5}
{2889E6B2-9CD1-437C-A43C-98CFAFF68B99} = {D59F1489-5D74-4F52-B78B-88037EAB2838}
{A9967817-2A2C-4C6D-A133-967A6062E9B3} = {75F709FD-8CC2-4558-A802-FE57086167C2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {78A935E9-8F14-448A-BEDF-360FB742F14E}
Expand Down
1 change: 1 addition & 0 deletions infra/scripts/write-runsettings.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $fileContents = @"
<DATASYNC_AZSQL_CONNECTIONSTRING>$($outputs.AZSQL_CONNECTION_STRING)</DATASYNC_AZSQL_CONNECTIONSTRING>
<DATASYNC_COSMOS_CONNECTIONSTRING>$($outputs.COSMOS_CONNECTION_STRING)</DATASYNC_COSMOS_CONNECTIONSTRING>
<DATASYNC_PGSQL_CONNECTIONSTRING>$($outputs.PGSQL_CONNECTION_STRING)</DATASYNC_PGSQL_CONNECTIONSTRING>
<DATASYNC_SERVICE_ENDPOINT>$($outputs.SERVICE_ENDPOINT)</DATASYNC_SERVICE_ENDPOINT>
<ENABLE_SQL_LOGGING>true</ENABLE_SQL_LOGGING>
</EnvironmentVariables>
</RunConfiguration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,54 @@
// See the LICENSE file in the project root for more information.

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Diagnostics.CodeAnalysis;

namespace Sample.Datasync.Server.Db;

public class AppDbContext : DbContext
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{

}

public DbSet<TodoItem> TodoItems => Set<TodoItem>();

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

public async Task InitializeDatabaseAsync()
{
_ = await Database.EnsureCreatedAsync();

const string datasyncTrigger = @"
CREATE OR ALTER TRIGGER [dbo].[{0}_datasync] ON [dbo].[{0}] AFTER INSERT, UPDATE AS
BEGIN
SET NOCOUNT ON;
UPDATE
[dbo].[{0}]
SET
[UpdatedAt] = SYSUTCDATETIME()
WHERE
[Id] IN (SELECT [Id] FROM INSERTED);
END
"
;

// Install the above trigger to set the UpdatedAt field automatically on insert or update.
foreach (IEntityType table in Model.GetEntityTypes())
{
string sql = string.Format(datasyncTrigger, table.GetTableName());
_ = await Database.ExecuteSqlRawAsync(sql);
}
}

[SuppressMessage("Style", "IDE0058:Expression value is never used", Justification = "Model builder ignores return value.")]
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Tells EF Core that the TodoItem entity has a trigger.
modelBuilder.Entity<TodoItem>()
.ToTable(tb => tb.HasTrigger("TodoItem_datasync"));

// Tells EF Core that the TodoList entity has a trigger.
modelBuilder.Entity<TodoList>()
.ToTable(tb => tb.HasTrigger("TodoList_datasync"));

base.OnModelCreating(modelBuilder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ internal Dictionary<string, Type> GetEntityMap(OfflineDbContext context)
/// <summary>
/// Retrieves the existing operation that matches an operation for the provided entity.
/// </summary>
/// <param name="entity">The entity being processed.</param>
/// <param name="entityEntry">The entity entry being processed.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe.</param>
/// <returns>The operation entity or null if one does not exist.</returns>
/// <exception cref="DatasyncException">Thrown if the entity ID of the provided entity is invalid.</exception>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Net;
using System.Net.Http.Json;

namespace CommunityToolkit.Datasync.Client.Test.Live;

[ExcludeFromCodeCoverage]
public class SampleServerTests
{
private readonly bool liveTestsAreEnabled = Environment.GetEnvironmentVariable("DATASYNC_SERVICE_ENDPOINT") is not null;
private readonly string serviceEndpoint = Environment.GetEnvironmentVariable("DATASYNC_SERVICE_ENDPOINT");

[SkippableFact]
public async Task Metadata_GetsSetByServer()
{
Skip.IfNot(this.liveTestsAreEnabled);

DateTimeOffset now = DateTimeOffset.UtcNow;
HttpClient client = new();
TodoItem source = new() { Title = "Test item" };
HttpResponseMessage response = await client.PostAsJsonAsync($"{this.serviceEndpoint}/tables/TodoItem", source);

response.Should().HaveHttpStatusCode(HttpStatusCode.Created);

TodoItem result = await response.Content.ReadFromJsonAsync<TodoItem>();
result.Id.Should().NotBeNullOrEmpty();
result.UpdatedAt.Should().NotBeNull().And.BeAfter(now);
result.Version.Should().NotBeNullOrEmpty();
result.Deleted.Should().BeFalse();
result.Title.Should().Be("Test item");
result.IsComplete.Should().BeFalse();

response.Headers.Location.Should().NotBeNull().And.BeEquivalentTo(new Uri($"{this.serviceEndpoint}/tables/TodoItem/{result.Id}"));
response.Headers.ETag.ToString().Should().Be($"\"{result.Version}\"");
}

// This must match the TodoItem class in the server project.
public class TodoItem
{
public string Id { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public string Version { get; set; }
public bool Deleted { get; set; }
public string Title { get; set; }
public bool IsComplete { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ internal void InitializeDatabase(bool clearEntities)
UPDATE
[dbo].[{0}]
SET
[UpdatedAt] = GETUTCDATE()
[UpdatedAt] = SYSUTCDATETIME()
WHERE
[Id] IN (SELECT [Id] FROM INSERTED);
END
Expand Down

0 comments on commit b155848

Please sign in to comment.