Qual è il modo migliore per evitare di aggiungere un record la cui chiave primaria è già presente in mnesia?
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?
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 .