2009-04-06 8 views
3

Angenommen, ich eine einfache Aufzeichnung Definition haben:Was ist der beste Weg, um das Hinzufügen eines Datensatzes zu verhindern, dessen Primärschlüssel bereits in Mnesien vorhanden ist?

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

ich eine einfache Funktion wollen, dass einer dieser Datensätze in eine Mnesia Datenbank hinzufügt. Aber ich möchte, dass es fehlschlägt, wenn es bereits einen Eintrag mit dem gleichen primären Schlüssel gibt.

(In den folgenden Beispielen, gehe ich davon aus bereits

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

definiert haben)

, die folgenden Werke aber scheint mir irgendwie hässlich ...

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. 

Diese funktioniert auch, ist aber auch hässlich:

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). 

Es unterscheidet sich von den oben, dass in der oben wirft

{error, bzzt_duplicate_primary_key}, 

während dieses

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

So wirft: gibt es einige Konvention, diese Art von Fehler für die Anzeige? Oder gibt es einen eingebauten Weg, dass ich Mnesia bekommen kann, um diesen Fehler für mich zu werfen?

Antwort

3

Ich denke, beide sind in Ordnung, wenn Sie Ihren Code recht machen, wie:

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). 

oder

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. 

Haben Sie Fehler oder Fehler zurückgeben werfen? Ich würde selbst einen Fehler zurückgeben. Wir teilen Code in mnesia work units auf - ein Modul mit einer Reihe von Funktionen, die grundlegende mnesia-Aktivitäten nicht in Transaktionen ausführen, und ein api-Modul, das die Arbeitseinheiten zu mnesia-Transaktionen mit Funktionen zusammenfügt, die der obigen sehr ähnlich sind .

+0

Erlang ist die eine Sprache, in der ich denke, dass die Rückgabe von Fehlern tatsächlich funktioniert. Pattern Matching und Fail Fast helfen dabei, so dass Fehler zurückkommen, was man damit meint, anstatt irgendwo irgendwo verloren zu gehen. –

+0

Ich stimme persönlich zu - wir neigen dazu, nur Fehler bei der Analyse von Benutzereingaben oder anderen Umständen zu werfen, bei denen ein Wurf eine "Rückkehr von vielen verschiedenen Orten hierher" darstellt und wir werden ... –