Come dovrebbe un ORM gestire la proprietà Id non assegnata?

1

Considera un ORM che associa le tabelle alle classi e le colonne alle proprietà. Come dovrebbe gestire una proprietà che si associa a una colonna di identità per oggetti non inseriti?

Ad esempio,

[Table("MyTable")]
public class MyMappedType
{
    [Column("Id")]
    public int Id 
    { 
        get
        { 
            // ...
        }
    }
}

MyMappedType myObj = new MyMappedType();
int id = myObj.Id; // Object not inserted into database so value is missing

Ci sono alcune opzioni differenti,

  1. Chiedi al getter della proprietà di lanciare un'eccezione. Questo sembra il più corretto perché se Id non è stato assegnato, qualsiasi valore restituito non ha significato. Tuttavia, va contro le linee guida che affermano che i metodi get di proprietà non dovrebbero generare eccezioni.

  2. Chiedi alla proprietà di restituire un valore speciale, ovvero 0 o -1 . Credo che nella maggior parte degli ORM le proprietà chiave siano inizializzate con il valore predefinito ( 0 ). Tuttavia, questo potrebbe essere fuorviante se c'è una riga nella tabella con il valore della colonna Identity di 0 .

  3. Forza le proprietà dell'ID come tipo Nullable<int> in modo che possa restituire null fino a quando non viene assegnato il valore.

Quale opzione è la migliore?

    
posta Mr Anderson 03.03.2017 - 03:55
fonte

2 risposte

1

Hai già risposto a te stesso. C'è un motivo per cui la maggior parte degli altri ORM va con l'opzione # 2.

Il numero 1 non dovrebbe nemmeno essere preso in considerazione, poiché lanciare un'eccezione da una proprietà è estremamente controintuitivo per l'utente finale.

# 3 è migliore, e principalmente mirror # 2, nel senso che assegna un valore predefinito ( null in questo caso) a una proprietà non assegnata. Tuttavia, i tipi di Nullable<T> sono difficili da utilizzare e costringono gli utenti a controllare sempre HasValue prima del confronto e altre complessità fastidiose.

Alla fine, l'unico svantaggio del # 2 è che non puoi avere una riga con un id di default(T) , ma che non ha nemmeno senso la maggior parte del tempo.
Si noti inoltre che non si è obbligati ad avere int come chiave primaria. L'implementazione predefinita di ApplicationUser di OWIN, ad esempio, utilizza Guid come tipo di chiave primaria ( uniqueidentifier in SQL Server).

    
risposta data 03.03.2017 - 09:55
fonte
0

Una soluzione potrebbe essere quella di evitare di lavorare direttamente con le entità ORM prima che siano state inserite nel database e di non utilizzare le entità ORM nella logica aziendale.

Se hai bisogno di lavorare con data prima di inserirlo, una soluzione comune sarebbe quella di creare un modello separato per quei dati che non fa parte della tua struttura ORM, usando un mappatore (es. AutoMapper in C #), o anche solo un codice di mappatura a mano per passare da uno all'altro.

Ci sono alcuni vantaggi del mapping dalla tua entità ORM a un modello separato; il vantaggio principale è che aiuta a separare il livello di business logic dal tuo livello di accesso ai dati, ma puoi anche includere altre proprietà nel tuo "modello di livello aziendale" mappato che non hanno bisogno di essere riflesse nel tuo database, così come avere la possibilità di mappare su diversi tipi senza influenzare lo schema del database sottostante.

Ad esempio:

[Table("Employee")]
public class Employee
{
    [Column("Id")]
    public int Id { get; set; }

    [Column("Name")]
    public string Name { get; set; }
}

public class EmployeeModel
{
    // OK - a Nullable<int> which isn't going to affect the DB schema
    // but it might be useful for the code which talks to the DB mapper
    public int? Id { get; set; }
    public string Name { get; set; }
}

// Assuming hand-rolled mapping code
public static class EmployeeModelExtensions
{
    public static Employee AsEmployee(this EmployeeModel model)
    {
        return new Employee
        {
            Id = model.Id ?? default(int),
            Name = model.Name,
        };
    }
}
    
risposta data 03.03.2017 - 09:55
fonte

Leggi altre domande sui tag