Qual è il modo migliore per evitare di aggiungere un record la cui chiave primaria è già presente in mnesia?

StackOverflow https://stackoverflow.com/questions/723680

  •  05-09-2019
  •  | 
  •  

Domanda

Supponiamo di avere una semplice definizione di record:

-record(data, {primary_key = '_', more_stuff = '_'}).

Voglio una funzione semplice che aggiunga uno di questi record a un database mnesia.Ma voglio che fallisca se c'è già una voce con la stessa chiave principale.

(Negli esempi seguenti, supponiamo che io abbia già definito

db_get_data(Key)->
    Q = qlc:q([Datum
               || Datum = #data{primary_key = RecordKey}
                      <- mnesia:table(data),
                  RecordKey =:= Key]),
    qlc:e(Q).

)

Quanto segue funziona, ma mi sembra un po' brutto...

add_data(D) when is_record(D, data)->
    {atomic, Result} = mnesia:transaction(fun()->
                                                  case db_get_data(D#data.primary_key) of
                                                      [] -> db_add_data(D);
                                                      _ -> {error, bzzt_duplicate_primary_key}
                                                  end
                                          end),

    case Result of
        {error, _} = Error -> throw(Error);
        _ -> result
    end.

Anche questo funziona, ma è anche brutto:

add_data(D) when is_record(D, data)->
    {atomic, Result} = mnesia:transaction(fun()->
                                                  case db_get_data(D#data.primary_key) of
                                                      [] -> db_add_data(D);
                                                      _ -> throw({error, bzzt_duplicate_primary_key})
                                                  end
                                          end).

Differisce da quanto sopra in quanto lancia quanto sopra

{error, bzzt_duplicate_primary_key},

mentre questo lancia

{error, {badmatch, {aborted, {throw,{error, bzzt_duplicate_primary_key}}}}}

COSÌ:esiste qualche convenzione per indicare questo tipo di errore?Oppure esiste un modo integrato per convincere la mnesia a generare questo errore per me?

È stato utile?

Soluzione

Penso che vadano bene entrambi, se solo rendi il tuo codice più carino, come:

add_data(D) when is_record(D, data)->

    Fun = fun() ->
                  case db_get_data(D#data.primary_key) of
                      [] -> db_add_data(D);
                      _  -> throw({error, bzzt_duplicate_primary_key})
                  end
          end,

    {atomic, Result} = mnesia:activity(transaction, Fun).

O

add_data(D) when is_record(D, data)->

    Fun = fun() ->
                  case db_get_data(D#data.primary_key) of
                      [] -> db_add_data(D);
                      _  -> {error, bzzt_duplicate_primary_key}
                  end
          end,

    {atomic, Result} = mnesia:activity(transaction, Fun),

    case Result of
        {error, Error} -> throw(Error);
        _              -> result
    end.

Gentili errori o restituisci errori?Io stesso restituirei un errore.Abbiamo suddiviso il codice in unità di lavoro mnesia: un modulo con una serie di funzioni che eseguono attività mnesia di base non nelle transazioni e un modulo API che "compone" le unità di lavoro in transazioni mnesia con funzioni che sembrano molto simili a quella sopra .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top