Nullable-Rückgabewert für ein generisches Argument

c# dapper generics nullable

Frage

Ich versuche, ein Modell mit Dapper in der Datenbank zu speichern. Ich habe die Parameter mit einem Eingabe / Ausgabe-Parameter eingerichtet, der ein int mit einem vorhandenen Primärschlüsselwert ist, der für ein Update verwendet wird.

public async Task<TKey> SaveAsync<TKey>(IGraph builder, IDataContext context = null)
{
    var parameters = this.GetParametersFromDefinition(builder, DefinitionDirection.In);

    // See if we have a key defined. If not, we assume this is a new insert.
    // Otherwise we pull the key out and assume it's an update.
    PropertyDefinition key = builder.GetKey();

    if (key != null)
    {
        parameters.Add(key.ResolvedName, key.PropertyValue, null, ParameterDirection.InputOutput);
    }
    else
    {
        throw new InvalidOperationException("The data graph did not have a primary key defined for it.");
    }

    await this.ExecuteProcedure(parameters, builder, context);

    object returnedId = parameters.Get<TKey>(key.ResolvedName);
    return returnedId == null ? default(TKey) : (TKey)returnedId;
}

private Task ExecuteProcedure(DynamicParameters parameters, IGraph builder, IDataContext context = null)
{
    ProcedureDefinition mapping = builder.GetProcedureForOperation(ProcedureOperationType.Insert);
    if (string.IsNullOrEmpty(mapping.StoredProcedure))
    {
        throw new InvalidOperationException("No stored procedure mapped to the builder.");
    }

    // Query the database
    return this.SetupConnection(
        context,
        (connection, transaction) => connection.ExecuteAsync(
            mapping.StoredProcedure,
            parameters,
            commandType: CommandType.StoredProcedure,
            transaction: transaction));
}

Es wird so aufgerufen:

this.Address.AddressId = await repository.SaveAsync<int>(graph);

Wenn ich die Parameter auswerte, sehe ich meine Eingabe- / Ausgabeparameter darauf.

Dynamische Parameter

Aber wenn ich versuche, diese Zeile in meinem Speicher auszuführen:

TKey returnedId = parameters.Get<TKey>(key.ResolvedName);

Mir wurde die folgende Ausnahme gegeben:

Ausnahme: Caught: "Versuch, einen DBNull in einen nicht nullbaren Typ zu konvertieren! Beachten Sie, dass out / return-Parameter keine aktualisierten Werte haben, bis der Datenstrom vollständig ist (nach 'foreach' für Query (..., gepuffert: false)). oder nachdem der GridReader für QueryMultiple freigegeben wurde) "(System.ApplicationException) Eine System.ApplicationException wurde abgefangen:" Versuch, einen DBNull in einen nicht nullbaren Typ zu konvertieren! Beachten Sie, dass out / return-Parameter erst im Datenstrom aktualisiert werden wird abgeschlossen (nach 'foreach' für Query (..., gepuffert: false) oder nachdem der GridReader für QueryMultiple freigegeben wurde) "Zeit: 21.07.15 10:19:48 PM Thema: [7200]

Ich gehe davon aus, dass dies ein Problem ist, bei dem der generische Typ in diesem Fall keine NULL-Werte zulässt, da es sich um eine Ganzzahl handelt. Liegt das daran, dass Dapper immer ein Nullwert zurückgibt? Ich habe gerade OUTPUT für die gespeicherte Prozedur einen konstanten Wert zugewiesen, um sicherzustellen, dass die Ausgabe etwas zugewiesen ist.

Wie kann ich daper arbeiten, indem ich ein NULL-Zeichen zurückgebe int? als generischer Typ?

Aktualisieren

Ich konnte es mit diesem Ansatz lösen. SO wird mich das als Antwort noch nicht posten lassen. Wenn das Zeitlimit abgelaufen ist, werde ich eine Antwort posten, es sei denn jemand anderes hat bessere Ideen.

object returnedId = parameters.Get<TKey>(key.ResolvedName);
if (returnedId == null)
{
    return default(TKey);
}

return (TKey)returnedId;

Akzeptierte Antwort

Wenn DBNull ein gültiger Wert ist und etwas anderes als Standard (TKey) bedeuten sollte (zB: default (int) = 0), und wenn TKey immer ein Werttyp ist, dann schränke TKey als Struktur ein:

public async Task<TKey?> SaveAsync<TKey>(IGraph builder, IDataContext context = null) where TKey : struct
{
    ...
}

Dann hol dir den Schlüssel so:

TKey? returnedId = parameters.Get<TKey?>(key.ResolvedName);

Der Rückgabetyp von SaveAsync spiegelt wider, dass der Schlüssel null sein kann. Wenn der Schlüssel niemals null sein sollte und DBNull standardmäßig auf TKey eingestellt werden soll, verwenden Sie einfach Folgendes:

public async Task<TKey?> SaveAsync<TKey>(IGraph builder, IDataContext context = null) where TKey : struct
{
    ...
    return parameters.Get<TKey?>(key.ResolvedName).GetValueOrDefault();
}


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum