277 messaggi dal 03 ottobre 2006
Se ho una formview che mostra i dati di una tabella "barca" dove all'interno ho una Navigation property "Skipper", come faccio a testare l'eventualità che questa property non sia null in modalità edit?

Nell'ItemTemplate della formview faccio così:
<div class="col-md-4"><%#: (Item.Skipper)== null ? false :Item.Skipper.Skippercheck %></div>
e funziona

ma nella EditItemTemplate, questa istruzione
<div class="col-md-4"><asp:CheckBox ID="cbs" Checked='<%# (Item.Skipper == null)? false : BindItem.Skipper.Skippercheck %>' runat="server" /></div>
fallisce perchè mi dice che BindItem non esiste nel contesto corrente

Se invece lascio così
<div class="col-md-4"><asp:CheckBox ID="cbs" Checked='<%# BindItem.Skipper.Skippercheck %>' runat="server" /></div>
mi da errore perchè la proprietà Skipper effettivamente è null su certe Barche
C'è una sintassi diversa da usare?
Grazie
277 messaggi dal 03 ottobre 2006
Per coloro a cui può interessare, ho risolto così usando il code behind
Nella <EditItemTemplate> ho messo
<div class="col-md-4"><asp:CheckBox ID="cbs" Checked='<%# Controlla(Item.Skipper) %>' runat="server" /></div>

Nel Code behind questo
public bool Controlla(Skipper s)
{
if (s != null)
return s.Skippercheck;
else
return false;
}

Non so se questo indichi che dovrebbe esistere una sintassi che risolva la questione senza il code behind ma così ha funzionato
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


Nel Code behind questo
public bool Controlla(Skipper s)
{
if (s != null)
return s.Skippercheck;
else
return false;
}

Ma in questo modo ti funziona il binding two-way? Credo che questa cosa sia l'equivalente di questo, che non usa BindItem ma Item.
<div class="col-md-4"><asp:CheckBox ID="cbs" Checked='<%# (Item.Skipper == null) ? false : Item.Skipper.Skippercheck %>' runat="server" /></div>

Oppure, se stai usando una versione recente di C#, puoi usare il conditional operator.
<div class="col-md-4"><asp:CheckBox ID="cbs" Checked='<%# Item.Skipper?.Skippercheck == true %>' runat="server" /></div>


Se vuoi usare il binding two-way credo che tu debba usare un DTO anziché le entità. In pratica, il DTO avrà l'esatta forma che ti serve per i form di modifica e poi, quando salvi, la converti a entità. Nel caso specifico, SkipperCheck dovrebbe essere una proprietà del DTO, senza annidarla dentro Skipper.

ciao,
Moreno
Modificato da BrightSoul il 05 novembre 2018 22.34 -

Enjoy learning and just keep making
277 messaggi dal 03 ottobre 2006
Purtroppo hai perfettamente ragione nel senso che avevo verificato troppo rapidamente e in effetti non mi fa il binding two-way
Però sono perplesso sulla necessità di usare un DTO (di cui sto cercando ora informazioni nel web)
Io provengo da anni di utilizzo di DAL BLL e ObjectDataSource e sto provando da poco ad usare quella che pareva una evoluzione cioè Entity Framework 6
In effetti pare semplificare molte operazioni, sto usando Code First come approccio ma dalle tue parole mi pare di capire che la creazione di una classe che poi si trasforma in entità non sia sufficiente per fare da tramite tra il livello di presentazione dati e il DB.
Di fatto mi stai chiedendo di costruire un livello intermedio di classi fedeli al dati che voglio mostrare per poi convertirle in entità ? Ho visto che ci sono strumenti che compiono questo lavoro automaticamente ma il fatto di dover usare queste strutture è una limitazione di EF 6 ?
Sto usando Entity POCO anzi Proxy POCO e la classe incriminata da cui devo ricavare la proprietà è definita così:
public class Barca
{
public int BarcaID { get; set; }
[StringLength(30)]
public string Modello { get; set; }
[StringLength(4)]
public string Anno { get; set; }
[StringLength(20)]
public string Bandiera { get; set; }
[StringLength(200)]
public string Base { get; set; }
[StringLength(30)]
public string Nome { get; set; }
public int Cabine { get; set; }
public int Bagni { get; set; }
public int Letti { get; set; }
public int Postiomol { get; set; }
public string Note { get; set; }
public int Ccosto { get; set; }
public string Regione { get; set; }

[ForeignKey ("Skipper") ]
public int? SkipperId { get; set; }
public virtual Skipper Skipper { get; set; }

[ForeignKey("Skipperpref")]
public int? SkipperIdpref { get; set; }
public virtual Skipper Skipperpref { get; set; }

public virtual ICollection<Tesserato> Tesserati { get; set; }
}

e io dovrei accedere a Skipper.Skippercheck della classe Skipper
Cambierebbe qualcosa se definissi
public virtual Skipper Skipper { get; set; }
come
public Skipper Skipper { get; set; } ?

lo dico con l'obiettivo di evitare un DTO...
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


Di fatto mi stai chiedendo di costruire un livello intermedio di classi fedeli al dati che voglio mostrare per poi convertirle in entità ?

Esatto, ed è una prassi molto comune perché le maschere di visualizzazione, inserimento e modifica sono quasi sempre diverse dalla struttura delle entità. E non solo: differiscono anche tra loro stesse quindi è perfettamente normale creare di DTO. Anzi, direi che è strano usare direttamente le entità perché il loro scopo è diverso: non servono a trasportare dati ma si occupano di proteggere il loro stato interno per mezzo di logica di business.


il fatto di dover usare queste strutture è una limitazione di EF 6 ?

No, assolutamente. Entity Framework ha già la sua corposa responsabilità di leggere e ripersistere grafi di entità. Non deve fare altro. Anzi, ti permette di proiettare una query LINQ (con il metodo Select) in un DTO quindi offre tutto quello che ti può servire. Qui se ne è parlato un po':
http://forum.aspitalia.com/forum/post/419915/Configurare-Webapi-Mvc5.aspx?PageIndex=1


lo dico con l'obiettivo di evitare un DTO...

Puoi anche evitarlo ma cercherò di farti capire cosa stai facendo con un'analogia.

In un appartamento esistono vari tipi di stanze con specifiche responsabilità, tra cui il bagno e la sala da pranzo. Puoi costruire un bagno che affaccia sulla sala da pranzo? Certo, se metti mattone su mattone non è che il muro crolla. Però, per motivi di decoro (e di legge), tra il bagno e la sala da pranzo deve esserci una ulteriore stanza (l'antibagno) che permette di far coesistere le responsabilità dell'una e dell'altra stanza all'interno della stessa casa.

Quindi, se mi chiedi: posso mettere le entità a contatto della UI? Io ti rispondo: certo, l'applicazione non crolla ma se ci metti un DTO è meglio. E non perché questo sia un dogma ma perché, come hai potuto sperimentare tu stesso, le esigenze del tuo modello di scrittura basato su Entity Framework e classi di entità mal si coniuga con le esigenze della UI.

ciao,
Moreno

Enjoy learning and just keep making
277 messaggi dal 03 ottobre 2006
Grazie mille delle precisazioni molto esaustive. Non mi resta che costruire il DTO
Ho inteso cosa è necessario fare, e dovrei aver capito come convertire da Entità a semplice classe per presentare i dati ma per ora non mi è chiaro come fare l'operazione contraria per poter poi salvare i dati nel DB
Puoi suggerirmi quale strumento automatico sia meglio usare?
Ho trovato "AutoMapper" da installare tramite NuGet, c'è di meglio ?
Uso Visual Studio 2017
277 messaggi dal 03 ottobre 2006
Mentre cerco di capire se ci sono strumenti migliori di AutoMapper che mi sembra un po troppo articolato, sto procedendo manualmente a costruire il DTO
La presentazione dei dati funziona perfettamente così:
public class BarcaDTO
{
public int barid { get; set; }
public Barca barca { get; set; }
public bool skippercheck { get; set; }
}
Ho creato questa classe portando fuori dalla entità barid per poterlo usare nella FormView come datakeynames, l'entità barca stessa perchè devo mostrarne tutte le proprietà e la skippercheck che era la proprietà di navigazione dell'entità che non riuscivo a mostrare direttamente
La FormView è fatta così:

<asp:FormView id="FVBarche" runat="server" SelectMethod="GetBarcaDTO" ItemType="SkipperClub.Models.BarcaDTO" DataKeyNames="barid" UpdateMethod="UpdateBarche" OnCallingDataMethods="FVBarche_CallingDataMethods" OnItemInserted="FVBarche_ItemInserted">

Ora però qual'è il metodo migliore per tornare indietro e salvare i dati nel DB ?
Prima funzionava perfettamente questa
public void UpdateBarche(int barid, ModelMethodContext context)
{
Barca item = null;
item = _db.ListBarche.Find(barid);
if (item == null)
{
context.ModelState.AddModelError("", String.Format("Barca con id {0} non trovata", barid));
return;
}

context.TryUpdateModel(item);
if (context.ModelState.IsValid)
{
_db.SaveChanges();
}
}
ma immagino di non poterla più usare perchè le modifiche ora non le faccio più direttamente sulla entità.
Devo usare le istruzioni seguenti o ci sono metodi più rapidi o automatici?

var barca = _db.ListBarche.Find(barid);
var entry = _db.Entry(barca);
qui vado a sostituire a mano ogni parametro di barca con i dati che prendo dal DTO modificato e poi salvo con
_db.SaveChanges();

Grazie
277 messaggi dal 03 ottobre 2006
non trovo da nessuna parte esempi di come si recuperano i dati modificati nella FormView che ora si appoggia alla DTO e li converta nell'entità per poi salvarli nel DB. Possibile che nel web tutti si appoggino ad AutoMapper ?

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.