edgedb / edgedb-net

The official .NET client library for EdgeDB
https://edgedb.com
Apache License 2.0
82 stars 9 forks source link

How do I use tuple in C# call to _EdgeDBclient.QuerySingleAsync() #75

Open EncompassingResidential opened 10 months ago

EncompassingResidential commented 10 months ago

Describe the bug

I submitted a question in Discord -> EdgeDb -> edgedb-dotnet on Mon, 1/15/24 but no one has responded as of 1/16/24 14:58 PAC.

I've tried multiple options for using a tuple in an INSERT statement, but I keep getting different warnings returned from EdgeDB. For Visual Studio 2022 C# .NET 7 code $ edgedb --version EdgeDB CLI 4.0.2+b26c502

Reproduction Include the code that is causing the error:

Here is the default.esdl

    type Artist {
        required                   artistname: str {
                constraint exclusive;
                constraint min_len_value(3);
                                }
                                   othernames: array<str>;
        required              wikipediapageid: int32;
                                    birthdate: datetime;
                                   familyname: tuple<first: str, middle: str, last: str>;
        required multi                 genres: Genre;
                 multi                 labels: MusicCompanyLabel;
        required                    timestamp: datetime;
        }

Here is the C# code (below code is the multiple iterations I tried and the EdgeDB errors that were returned):

        string familyNameFirst = "";
        string familyNameMiddle = "";
        string familyNameLast = "";
        if (artist.FamilyName != null) {
            familyNameFirst  = string.Join(", ", artist.FamilyName.Item1);
            familyNameMiddle = string.Join(", ", artist.FamilyName.Item2);
            familyNameLast   = string.Join(", ", artist.FamilyName.Item3);
        }

            try
            {
                var result = await _EdgeDBclient.QuerySingleAsync<Artist>(
                    " INSERT Artist " +
                    " { artistname      := <str>$name, " + 
                    "   othernames      := <array<str>>$onam, " +
                    "   wikipediapageid := <int32>$wpid, " +
                    "   birthdate       := <datetime>$bdat, " +
                    "   familyname      := <tuple< first: <str>$fname, middle: <str>$mname, last: <str>$lname >>, " +
                    "   genres          := <array<str>>$genr, " +
                    "   labels          := <array<str>>$labl, " +
                    "   timestamp       := <datetime>$ptst } ",
                                        new
                                        {
                                            name = artist.ArtistName,
                                            onam = otherNamesString,
                                            wpid = artist.WikipediaPageID,
                                            bdat = artist.BirthDate,
                                            fname = familyNameFirst,
                                            mname = familyNameMiddle,
                                            lname = familyNameLast,
                                            genr = genreString,
                                            labl = labelString,
                                            ptst = artist.PageTimeStamp
                                        });
            }
            catch (EdgeDB.EdgeDBErrorException ex)
            {
                Console.WriteLine($"{DateTime.Now} BandServer InsertArtistAsync for {artist.ArtistName}, WikiPageID {artist.WikipediaPageID} error from EdgeDB: ( {ex.Message} )");
                return false;
            }

Here are the various versions I've tried and the error returned:

// "   familyname      := tuple{ first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
//  object type or alias 'default::tuple' does not exist
//
// "   familyname      := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
// invalid target for property 'familyname' of object type 'default::Artist': 'std::FreeObject'
//         (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')
//
// "   familyname      := tuple<first: <str>$fname, middle: <str>$mname, last: <str>$lname>, " +
// Unexpected ':'
//
// "   familyname      := tuple<first <str>$fname, middle <str>$mname, last <str>$lname>, " +
// Missing '['
//
// "   familyname          := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
// invalid target for property 'familyname' of object type 'default::Artist': 
// 'std::FreeObject' (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')
//
// "   familyname          := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
//
// "   familyname      := <tuple< first := $fname, middle := $mname, last := $lname >>, " +
// Unexpected ':='
//
// "   familyname      := <tuple< first := <str>$fname, middle := <str>$mname, last := <str>$lname >>, " +
// Unexpected ':='
//
//"   familyname      := <tuple< first : <str>$fname, middle : <str>$mname, last : <str>$lname >>, " +
// Missing keyword 'TYPE'

Expected behavior

Trying to not get and error and INSERT the C# tuple properly into the INSERT statement.

Versions (please complete the following information):

$ dotnet --version 8.0.100 Frameworks MicrosoftAspNetCoreApp MicrosoftNETCoreApp Packages EdgeDB.Net.Driver (1.3.0) MicrosoftAspNetCore.OpenApi (7.0.10) Swashbuckle.AspNetCore (6.5.0) System.Net.Http.Json (8.0.0) - OS: Windows 11 - EdgeDB version: - EdgeDB CLI version: - `edgedb-net` version: - .NET version: **Additional context**
raddevon commented 10 months ago

You could try this:

familyname := <tuple<first:str, middle:str, last:str>>$familyname

You might also consider breaking out familyname as a separate object type. Those can be easier to wrangle than tuples.

quinchs commented 10 months ago

Crossposting from Discord:

from just looking at the code you provided, I noted some immediate problems:


for this error:

Code: " familyname := { first := $fname, middle := $mname, last := $lname }, " + Error: invalid target for property 'familyname' of object type 'default::Artist': 'std::FreeObject' (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')


Its telling you that you're trying to cast a free object to a tuple, the `{ x := y, ...}` syntax is a free object in EdgeDB, to specify a tuple you can use `(x, y, z, ...)` syntax.
fixing these issues seems to work on my end
EncompassingResidential commented 10 months ago

Hi Quin,

Did you see my question on Discord / edgedb-net about nullable C# class field that is getting runtime error "EdgeDB.MissingCodecException: Cannot find valid codec for System.Nullable`1[System.DateTimeOffset]" ?

Sincerely and Thanks, John Ritz, Software Engineer II 503-309-6411 cell @.*** www.linkedin.com/in/johntritz https://github.com/EncompassingResidential/Band-Tree

On Wed, Jan 17, 2024 at 10:18 AM Quin Lynch @.***> wrote:

Crossposting from Discord:

from just looking at the code you provided, I noted some immediate problems:

  • genres and labels are types within the schema, but in the code your casting them to <array> which doesn't insert/select them
  • familyname in the code doesn't contain type casts for arguments, resulting in this error:

QueryError: missing a type cast before the parameter | 1 | INSERT Artist { artistname := $name, othernames := <array>$onam, wikipediapageid := $wpid, birthdate := $bdat, familyname := { first := $fname, middle := $mname, last := $lname }, genres := <array>$genr, labels := <array>$labl, timestamp := $ptst } | ^^^^^^

for this error:

Code: " familyname := { first := $fname, middle := $mname, last := $lname }, " + Error: invalid target for property 'familyname' of object type 'default::Artist': 'std::FreeObject' (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')

Its telling you that your trying to cast a free object to a tuple, the { x := y, ...} syntax is a free object in EdgeDB, to specify a tuple you can use (x, y, z, ...) syntax. fixing these issues seems to work on my end

— Reply to this email directly, view it on GitHub https://github.com/edgedb/edgedb-net/issues/75#issuecomment-1896362353, or unsubscribe https://github.com/notifications/unsubscribe-auth/AWOLCDNAVLEGVI5NYECF263YPAIVRAVCNFSM6AAAAABB5SXZJKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOJWGM3DEMZVGM . You are receiving this because you authored the thread.Message ID: @.***>