14 messaggi dal 20 novembre 2006
Ciao a tutti.
Ho da poco iniziato ad utilizzare Entity Framework Code First.
Sto provando ad inserire il seguente oggetto :

public class Customer
{
public string UserName { get; set; }
public string Password { get; set; }
public StatoContatto Stato { get; set; }
}

public class StatoContatto
{
public int Id { get; set; }
public string Nome { get; set; }
}

L'inserimento del nuovo customer avviene cosi :

static public void CreaCliente(Customer cliente)
{
cliente.Stato = GetStato("Da Lavorare");
using (var clienti = new CustomerContest())
{
clienti.Customers.Add(c);
clienti.SaveChanges();
}
}

static public StatoContatto GetStato(string stato)
{
using (var clienti = new CustomerContest())
{
var risultato = clienti.Stati
.Where(stat => stat.Nome == stato);
return risultato.First();
}
}

Dove la funzione "GetStato" recupera tramite Entity Framework lo stato già presente nel DB.

Il mio problema è che quando salva il nuovo customer salva anche un nuovo StatoContatto sul DB invece di relazionarlo con quello già presente e che avevo letto in precedenza.

Sono sicuro che è una cavolata , ma ci sto sbattendo la testa e non riesco a vedere la soluzione.

Qualcuno può darmi dei chiarimenti !?

Vi ringrazio.

Mario Muti
89 messaggi dal 13 marzo 2010
Ciao,

il comportamento è dovuto al fatto che l'oggetto StatoContatto non è tracciato (sarebbe meglio dire "attachato" :-)) al DBContext.
Ti ricordo che il DBContext è (in modo semplicistico) l'oggetto che si occupa, fra le altre cose, di tracciare lo stato degli oggetti a lui assegnati. Se tu vai a creare un nuovo oggetto Customer con al suo interno un nuovo oggetto StatoContatto e chiedi al DBContext di aggiungerli al DB, il buon DBContext, non avendo altre informazioni circa i due oggetti che gli indicihi, marca ambedue gli oggetti come ADDED e quindi al momento dell'aggiornamento del DB saranno generate due statement INSERT.

Per evitare questo hai due possibilità:
(1) Nella classe Customer aggiungi una proprietà StatoContattoID, di tipo int, che fa le veci di una FK verso StatoContatto e quindi in Customer vai ad assegnare tale ID invece dell'oggetto StatoContatto:

static public void CreaCliente(Customer cliente)
{
var stato = GetStato("Da Lavorare");
using (var clienti = new CustomerContest())
{
cliente.StatoContattoID = stato.ID;
clienti.Customers.Add(cliente);
clienti.SaveChanges();
}
}

(2) Una volta che hai ricavato lo StatoContatto che ti interessa lo associ al DBContext, in modo che questo venga marcato come UNCHANGED. Successivamente assegni lo StatoContatto al tuo Customer, in questo modo (N.B. La collection dei Customer del DBContext l'ho indicata con clienti.Clienti):

static public void CreaCliente(Customer cliente)
{
var stato = GetStato("Da Lavorare");
using (var clienti = new CustomerContest())
{
clienti.Clienti.Attach(cliente);
cliente.Stato = stato;
clienti.Customers.Add(cliente);
clienti.SaveChanges();
}
}

Ti consiglio di dare una lettura al libro "Entity Framework In Action" di Stefano Mostarda, edizioni Manning (http://www.manning.com/mostarda/), che benchè faccia riferimento alla versione 4 di EF, continua ad essere ottimo testo di riferimento per gli aspetti fondamentali di EF ed in particolar modo per la gestione dello stato delle entities.

Ciao
Federico
Modificato da federico.orlandini il 09 settembre 2013 10.33 -
14 messaggi dal 20 novembre 2006
Ok, grazie Federico.
Evidentemente ho bisogno di approfondire ulteriormente, seguiro il tuo consiglio in merito al libro.
Grazie ancora.

Mario Muti

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.