Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(#210) Fixing UpdatedAt property in sample. #218

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading