2010-01-04 18 views
6

Ho la seguente classe:Nibire eseguire gli aggiornamenti su select?

public class Product 
{ 
    public virtual Guid Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Decimal PricePerMonth { get; set; } 
    public virtual BillingInterval DefaultBillingInterval { get; set; } 
    public virtual string AdditionalInfo { get; set; } 
} 

e la mappatura si presenta così:

<class name="Product" table="Products"> 
    <id name="Id" column="ProductId"> 
     <generator class="guid.comb"/> 
    </id> 
    <property name="Name" column="ProductName" not-null="true" type="String" /> 
    <property name="PricePerMonth" column="PricePerMonth" not-null="true" type="Decimal" /> 
    <property name="DefaultBillingInterval" type="int" not-null="true" /> 
    <property name="AdditionalInfo" type="string" not-null="false" /> 
</class> 

Io uso una classe Repository<T> con il seguente metodo (Session è una proprietà che restituisce la sessione corrente):

public IEnumerable<T> FindAll(DetachedCriteria criteria) 
{ 
    return criteria.GetExecutableCriteria(Session).List<T>(); 
} 

Ora quando eseguo quanto segue (la sessione è la stessa sessione utilizzata nel repository):

IEnumerable<ProductDTO> productDTOs = null; 
using(ITransaction tx = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
{ 
    var products = repository.FindAll(new DetachedCriteria.For<Product>().Add(Restrictions.Like("Name", "Some Product%"))); 
    productDTOs = ToDTOs(products); 
    tx.Commit(); 
} 
// Do stuff with DTO's 

Il commettere affermazione è lì, perché io uso un livello di servizio che impegna automaticamente ogni transazione se non errori durante. Ho appena crollato il mio livello di servizio qui per una più facile visualizzazione ..

Il mio metodo ToDTOs converte semplicemente un DTO:

private IEnumerable<ProductDTO> ToDTO(IEnumerable<Product> products) 
{ 
    return products.Select(x => new ProductDTO() 
    { 
     Id = x.Id, 
     Name = x.Name, 
     PricePerMonth = x.PricePerMonth, 
     AdditionalInfo = x.AdditionalInfo 
    }).ToList(); 
} 

mio registro NHibernate mostra il seguente output:

2010-01-04 19:13:11,140 [4] DEBUG NHibernate.SQL - SELECT ... From Products ... 
2010-01-04 19:13:11,237 [4] DEBUG NHibernate.SQL - UPDATE Products ... 
2010-01-04 19:13:11,548 [4] DEBUG NHibernate.SQL - UPDATE Products ... 
... 

Così selezionando i prodotti emette una dichiarazione di aggiornamento per ogni prodotto restituito quando la sessione si impegna, anche se nulla è stato modificato nei prodotti.

Qualche idea?

+0

Questo * veramente * come viene implementato l'entità? Non ti credo –

+0

È ... È vero, avevo una lista di ordini a cui era collegato il prodotto, ma ho rimosso questa lista, sia dalla classe che dalla mappatura (come mostrato qui) ed è lo stesso risultato .. La mia confusione è ancora più profonda dal fatto che ciò non accade alle altre mie entità .. –

risposta

7

Ho avuto questo effetto solo quando avevo un'entità che non restituisce lo stesso valore dalla proprietà del valore che gli è stato assegnato. Quindi viene trattato come sporco da NH.

Esempio:

class Foo 
{ 
    private string name; 

    public string Name 
    { 
    // does not return null when null had been set 
    get { return name ?? "No Name"; } 
    set { name = value; } 
    } 

} 

Questo è come vorrei scrivere il file di mapping.

<class name="Product" table="Products"> 
    <id name="Id" column="ProductId"> 
     <generator class="guid.comb"/> 
    </id> 
    <property name="Name" column="ProductName" not-null="true" /> 
    <property name="PricePerMonth" not-null="true" /> 
    <property name="DefaultBillingInterval" not-null="true" /> 
    <property name="AdditionalInfo" /> 
</class> 

Non è necessario specificare i tipi. Sono determinati da NHibernate in fase di esecuzione.

+0

Aha, quindi deve essere l'enumerazione BillingInterval che causa il problema poiché è mappato come un int? Come mappare un enum (supportato da un int) senza che siano presenti le istruzioni di aggiornamento? –

+0

Non è necessario specificare alcun tipo quando si mappano enumerazioni. –

+0

Funziona anche quando il database memorizza DefaultBillingInterval come smallint (i valori enum hanno i valori interi 3,6,12)? –

1

Post precedente, ma forse questo aiuterà qualcuno in fondo alla strada.

Ho una libreria di classi C# di archivio dati (Oracle come database). Il valore della tabella era NULL ma nel mio repo il valore era definito come Decimale e avrebbe dovuto essere? Decimale. Ciò risolveva questo problema di aggiornamento durante l'esecuzione di una selezione.

+1

Un altro scenario in cui è possibile ottenere un UPDATE non previsto è quando una nuova proprietà è stata aggiunta al mapping del database e un record viene letto da un database creato con la versione precedente del mapping. –

+0

James, buono a sapersi! –

Problemi correlati