SpacetimeDB icon indicating copy to clipboard operation
SpacetimeDB copied to clipboard

CSharp quickstart does not compile

Open BinarySpike opened this issue 7 months ago • 9 comments
trafficstars

On https://spacetimedb.com/docs/modules/c-sharp/quickstart

The below code does not compile:

[Reducer]
public static void SetName(ReducerContext ctx, string name)
{
    name = ValidateName(name);

    var user = ctx.Db.user.Identity.Find(ctx.Sender);
    if (user is not null)
    {
        user.Name = name;
        ctx.Db.user.Identity.Update(user);
    }
}

I get the errors:

...server\Lib.cs(30,12): error CS1061: 'Module.User?' does not contain a definition for 'Name' and no accessible extension method 'Name' accepting a first argument 
of type 'Module.User?' could be found (are you missing a using directive or an assembly reference?) [...\server\StdbModule.csproj]

...server\Lib.cs(31,35): error CS1503: Argument 1: cannot convert from 'Module.User?' to 'Module.User' [...\server\StdbModule.csproj]

This is due to .Find(...) returning a Module.User? (nullable) and both user.Name and Identity.Update(...) expecting a Module.User (not nullable)

This is also the case for the following functions ClientConnected and ClientDisconnected

🤔

BinarySpike avatar Apr 19 '25 04:04 BinarySpike

I'm not able to reproduce this issue. The not null check should be sufficient here 🤔

Can you share your StdbModule.csproj and spacetime --version?

bfops avatar Apr 21 '25 17:04 bfops

Hello, I am also facing this issue following the quickstart.

spacetime --version output: spacetimedb tool version 1.1.0; spacetimedb-lib version 1.1.0;

csproj file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8</TargetFramework>
    <RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SpacetimeDB.Runtime" Version="1.1.0" />
  </ItemGroup>

</Project>

using VScode:

Version: 1.99.3 (user setup)
Commit: 17baf841131aa23349f217ca7c570c76ee87b957
Date: 2025-04-15T23:18:46.076Z
Electron: 34.3.2
ElectronBuildId: 11161073
Chromium: 132.0.6834.210
Node.js: 20.18.3
V8: 13.2.152.41-electron.0
OS: Windows_NT x64 10.0.19045

ScherrerMichael avatar Apr 28 '25 05:04 ScherrerMichael

Thanks @ScherrerMichael! It's the same code that's causing an error? What build command are you using?

bfops avatar Apr 28 '25 17:04 bfops

No problem! Yes it is the exact same code, everything else works fine except for handling of the null-able type reference user, despite enabling the Nullable cs project directive. I even tried adding the #nullable enable annotation to no success.

I used spacetime publish <server-name> and spacetime publish --project-path <server-path> <server-name> as well.

ScherrerMichael avatar Apr 28 '25 20:04 ScherrerMichael

@ScherrerMichael what does your dotnet --info say? I think we will probably just fix this with some more explicit null-casting, but it would be good to know why is happening for some people and not others.

bfops avatar Apr 29 '25 17:04 bfops

This is my output for dotnet --info:

.NET SDK:
 Version:           8.0.408
 Commit:            e6663e9b3d
 Workload version:  8.0.400-manifests.5ac61b9b
 MSBuild version:   17.11.26+2b19be476

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.408\

.NET workloads installed:
Configured to use loose manifests when installing new manifests.
 [wasi-experimental]
   Installation Source: SDK 8.0.400
   Manifest Version:    8.0.15/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.workload.mono.toolchain.current\8.0.15\WorkloadManifest.json
   Install Type:        FileBased


Host:
  Version:      9.0.4
  Architecture: x64
  Commit:       f57e6dc747

.NET SDKs installed:
  5.0.402 [C:\Program Files\dotnet\sdk]
  8.0.311 [C:\Program Files\dotnet\sdk]
  8.0.408 [C:\Program Files\dotnet\sdk]
  9.0.203 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 5.0.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 5.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 5.0.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 9.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  arm64 [C:\Program Files\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\arm64\InstallLocation]
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not set

global.json file:
  C:\Users\Michael\Desktop\SpaceMMO\server\global.json

Learn more:
  https://aka.ms/dotnet/info
  Not set

global.json file:
  C:\Users\Michael\Desktop\SpaceMMO\server\global.json

Learn more:
  https://aka.ms/dotnet/info

  Not set

global.json file:
  C:\Users\Michael\Desktop\SpaceMMO\server\global.json

Learn more:
  Not set

global.json file:
  Not set
  Not set

global.json file:
  C:\Users\Michael\Desktop\SpaceMMO\server\global.json

Learn more:
  Not set

global.json file:
  C:\Users\Michael\Desktop\SpaceMMO\server\global.json

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
global.json file:
  C:\Users\Michael\Desktop\SpaceMMO\server\global.json

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download
  https://aka.ms/dotnet/download

ScherrerMichael avatar Apr 29 '25 17:04 ScherrerMichael

Thank you! That all seems reasonable.. I guess we'll just update the quickstart and call it a day.

bfops avatar Apr 30 '25 17:04 bfops

Hi, I also tried doing the quickstart on the latest version (SpacetimeDB.Runtime 1.1.1), and .net gives me the "cannot resolve symbol 'SpacetimeDB'" Error. I'm using Rider IDE (Jetbrains). I also opened it with Visual Studio 2022 and the error it gives me is that the wasi-wasm workload is not compatible with .Net 9... tho the project is using .Net 8. I do have both installed.

EDIT: I executed "spacetime build" inside the folder where the project is and, now it doesn't give any errors... Perhaps you could add a warning in the quickstart step by step.

Noruka avatar May 03 '25 21:05 Noruka

Hi, I also tried doing the quickstart on the latest version (SpacetimeDB.Runtime 1.1.1), and .net gives me the "cannot resolve symbol 'SpacetimeDB'" Error. I'm using Rider IDE (Jetbrains). I also opened it with Visual Studio 2022 and the error it gives me is that the wasi-wasm workload is not compatible with .Net 9... tho the project is using .Net 8. I do have both installed.

EDIT: I executed "spacetime build" inside the folder where the project is and, now it doesn't give any errors... Perhaps you could add a warning in the quickstart step by step.

I had similar issues. I had to put the .sln file in a parent folder and move global. json up too in some cases. Not sure why any of that is required...

See: https://github.com/clockworklabs/SpacetimeDB/issues/2599

BinarySpike avatar May 03 '25 23:05 BinarySpike

tl;dr @rekhoff I think the most straightforward fix is to just update the quickstart (and tutorial) with different null-handling, but I'd be interested to know if we have a way of reproducing this (and ideally adding a regression test), since I haven't been able to get the same failure.

bfops avatar May 05 '25 20:05 bfops

I was also unable to reproduce the issue. I'd hate to update the null handling without confidence that would resolve the issue for others in this state.

A few things to try might be:

  1. Ensure that the global.json file is targeting 8.0.408 by running: dotnet new globaljson --sdk-version 8.0.408
  2. Do you get the error is there is a suppressed null check like so:
[Reducer]
public static void SetName(ReducerContext ctx, string name)
{
    name = ValidateName(name);

    var user = ctx.Db.user.Identity.Find(ctx.Sender);
    if (user is not null)
    {
        user.Name = name;
        ctx.Db.user.Identity.Update(user!);
    }
}

(Notice the ! after user in ctx.Db.user.Identity.Update(user!);)

rekhoff avatar May 09 '25 22:05 rekhoff

(we would also need to update user.Name to user!.Name)

bfops avatar May 16 '25 17:05 bfops

We might be better off using a pattern matching variable assignment here, both from the perspective of the raised nullable struct issues and also just for the sake of code style:

[Reducer]
public static void SetName(ReducerContext ctx, string name)
{
    name = ValidateName(name);

    if (ctx.Db.user.Identity.Find(ctx.Sender) is User user)
    {
        user.Name = name;
        ctx.Db.user.Identity.Update(user);
    }
}

This way it's never perceived by the analysers as a nullable type to begin with.

Another thing to check is to make sure you've defined the User type as a class and not a struct; C# really doesn't handle nullable structs in nearly so elegant a fashion as nullable classes. If you need it to be a struct for some reason, user!.Value is your frenemy.

wes-sleeman avatar May 29 '25 22:05 wes-sleeman

Successfully merged #3173, should concludes this issue.

rekhoff avatar Aug 26 '25 22:08 rekhoff