AutoMapper DTO e POCO Object

Una delle soluzioni architetturali che ho imparato ad apprezzare ed utilizzare nel corso degli anni è quella che prevede:

– uno strato Model, contenente una o più entità POCO referenziate tra loro;
– uno strato Repository per l’accesso ai dati;
– uno strato Service;
– uno strato Presentation, che contiene le nostre pagine html/aspx (o le view se sviluppate in asp.net mvc).

Una pratica che vi consiglio caldamente di seguire è di non utilizzare gli oggetti POCO per la loro rappresentazione grafica, ma di affidarvi a dei DTO di appoggio.
In tal senso, oggi ho scoperto un utilissimo metodo fornito da AutoMapper, in sede di creazione della Map tra un oggetto POCO ed un DTO.

1
2
cfg.CreateMap<User, ViewModel.User.dtoUser>()
.ForMember(dest => dest.Property, opt => opt.NullSubstitute("N/A"))

L’utilizzo del metodo NullSubstitute vi consente di associare automaticamente un valore string di default nel caso in cui la proprietà risulti essere NULL. (nel mio caso voglio visualizzare N/A nel caso in cui Property sia NULL).

Related Posts:

Asp.Net carrello Paypal: problema con le spese di spedizione

SottoTitolo: (PayPal Shipping costs not added to total)

Negli ultimi tempi sto concentrando i miei sforzi, in raccordo con Emanuele, sullo sviluppo di una piattaforma e-commerce che abbiamo creato da zero (completamente customizzata – che, spero, andrà online molto presto).

Ho da poco riscontrato un problema nella gestione delle spese di spedizione da parte di PayPal.
Una premessa è dovuta: in sede di raccolta delle specifiche abbiamo deciso di ricorrere a PayPal WebSite Payments Standard (WPS) per il semplice motivo che, nonostante non fornisca tutta una serie di strumenti utili, consente al cliente di effettuare il pagamento anche nel caso in cui non possieda un account PayPal.

Il problema risiede nella gestione che PayPal fa dei costi di spedizione.
La variabile interessata è “shipping”. Leggendo il manuale fornito, alla voce “HTML Variables for Website Payments Standard” si legge che:

shipping – Optional – The cost of shipping this item. If you specify shipping and shipping2 is not defined, this flat amount is charged regardless of the quantity of items purchased.
This use of the shipping variable is valid only for Buy Now and Add to Cart buttons.
Default – If profile-based shipping rates are configured, buyers are charged an amount according to the shipping methods they choose.

Purtroppo, dopo vari test, mi sono reso conto che ciò non corrisponde al vero. Difatti, nonostante io abbia configurato l’account PayPal, alla sezione costi di spedizione, dicendo espressamente di volerli customizzare, il motore non leggeva in alcun modo il valore della variabile che gli passavo.

Dopo un bel pò di tempo passato a leggere il forum (peraltro colgo l’occasione per fare un complimento alla piattaforma x.com), ho trovato questo link: Shipping not being passed to paypal, dove molti sviluppatori lamentavano il fatto che la variabile che in realtà deve essere usata sia “handling_cart”. Sempre dallo stesso manuale si legge che:

handling_cart – Optional – Single handling fee to be charged cart-wide. If handling_cart is used in multiple Add to Cart buttons, the handling_cart value of the first item is used.

Leggendo il forum, mi trovo daccordo con gli sviluppatori. Piuttosto che modificare la documentazione, peraltro non ancora sistemata dopo ben 2 anni, sarebbe il caso che PayPal provvedesse a sistemare il proprio motore interno in modo che la variabile shipping assolva correttamente il suo compito.

Spero di essere stato d’aiuto a qualcuno.

Related Posts:

Asp.Net jQuery validate dialog: this[0] is undefined

Sviluppare in asp.net webform e jquery è sicuramente un’attività che consente di realizzare un prodotto con un codice molto pulito e ben strutturato, delegando correttamente le diverse azioni ad ogni modulo.

Tuttavia, al contrario di quanto non avvenga in asp.net mvc, bisogna fare molta attenzione a ciò che succede dietro le scene.

Oggi per esempio mi sono imbattuto in un comportamento che non avevo notato prima.

La situazione è quella in cui, al click di un pulsante, si apra una finestra popup, realizzata tramite jQuery UI dialog. La finestra conterrà una serie di campi e due pulsanti (annulla, salva): l’obiettivo è consentire l’inserimento su DB di una generica entità (ie: un utente).

In aggiunta, ho inserito una serie di regole di validazione ricorrendo a jQuery validation.
Tuttavia, sul change del campo di testo, la console javascript restituisce questo errore:

this[0] is undefined

Questo avviene perchè il dialog viene creato al di fuori del form presente nella master page (come riportato nella figura sottostante).

html di un form asp.net con un jquery dialog aperto

Per ovviare a questo problema, si deve intervenire sull’evento open del dialog, in modo che il codice del dialog venga inserito all’interno del form.

Di seguito uno snippet del codice necessario:

1
2
3
4
5
6
7
8
9
10
11
$("#popup").dialog({
  title: 'titolo',
  autoOpen: false,
  close: function () { $(this).remove(); },
  open: function () {
    $(this).parent().appendTo($('#aspnetForm'));
  },
  modal: true,
  width: 600,
  height: 300,
  ...

Related Posts:

ASP.NET Wizard Control e UpdatePanel

Con Emanuele stiamo sviluppando un prodotto con una deadline parecchio vicina.
Per questo motivo, dovendo sviluppare un wizard per finalizzare il pagamento su un prodotto Ecommerce, ho scelto di far uso del controllo fornito dal framework .NET ASP:Wizard.

Come tutti i controlli forniti da .net, è molto semplice da utilizzare e, sebbene mi piaccia poco ricorrere al loro utilizzo a causa del basso di livello di customizzazione che possiedono, ho dovuto comunque farne ricorso.

Nel tentativo di fare un qualcosa di fatto bene, ho scelto di accoppiare un UpdatePanel al controllo Wizard.
Ovviamente è crashato tutto, o meglio, il controllo Wizard non consentiva più di navigare tra i vari step a causa del non corretto refresh dell’UpdatePanel.

Dopo un’oretta di tentativi, devo ringraziare Jean Paul per aver fornito la soluzione su stackoverflow.

Related Posts:

Visual Studio CTP: c# async ed await

Qualche settimana fa è stata rilasciata una nuova CTP nella quale possiamo trovare alcune anticipazioni della nuova versione di c#.

Una delle più interessanti è rappresentata dalla presenza di due nuove parole chiavi: async ed await.

Allo stato attuale per effettuare una chiamata remota, sapendo che spesso tutto gira dietro un unico Thread, bisogna ricorrere alla tecnica delle callback il che, tuttavia, comporta un blocco del flusso applicativo.

Grazie ad async ad await non dovremo più far ricorso ai callback ma potremo rendere asincroni i metodi che riterremo più opportuni per le nostre finalità.

Ovviamente questo in sintesi, per degli esempi di codice riferitevi al link qui sotto.

(via C# Frequently Asked Questions)

Related Posts:

Evitare NHibernate.ObjectNotFoundException

Una delle caratteristiche che rendono “potente” l’utilizzo di ORM nelle nostre web-application, è la possibilità fornitaci dal lazy load.

Tuttavia, può succedere che quando referenziamo un’altra entità (ad esempio utilizzando Fluent NHibernate) il dato che cerchiamo di tirare su non esista. NHibernate restituirà, quindi, un eccezione di tipo NHibernate.ObjectNotFoundException.

Per evitare questa situazione, è necessario mappare la colonna di reference come segue:

1
2
3
4
References(x => x.ProprietàReferenziata)
  .Column("foreignKeyColumn")
  .Not.LazyLoad()
  .NotFound.Ignore();

(via stackoverflow)
(via fluent nhiberante wiki)

Related Posts:

ASP.NET ListView: itemPlaceHolder InvalidOperationException

Sto approcciandomi per la prima all’utilizzo del componente ListView, nettamente più potente e flessibile (soprattutto in termini di personalizzazione del layout) rispetto al GridView.

Seguendo l’esempio di Scott Gu, ho creato un ListView del tipo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<asp:ListView runat="server" ID="temp">
  <LayoutTemplate>
  <table>
    <asp:PlaceHolder ID="itemContainer" runat="server">
    </asp:PlaceHolder>
  </table>
  </LayoutTemplate>
 
  <ItemTemplate>
  <tr>
    <td>
      <%#Eval("Descrizione") %>
    </td>
  </tr>
  </ItemTemplate>
</asp:ListView>

Tuttavia, ricevo questo errore a run-time:

È necessario specificare un segnaposto di elemento nell’elemento ListView ‘temp’. Specificare un segnaposto di elemento impostando la proprietà ID di un controllo su “itemPlaceholder”. Il controllo segnaposto di elemento deve inoltre specificare runat=”server”.

Andreas Kraus suggerisce la soluzione corretta, cioè sostituire il valore itemContainer con itemPlaceHolder (nuovo valore di default dell’ ItemPlaceHolderId di ListView)

Il codice corretto, quindi, è:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<asp:ListView runat="server" ID="temp">
  <LayoutTemplate>
  <table>
    <asp:PlaceHolder ID="itemPlaceHolder" runat="server">
    </asp:PlaceHolder>
  </table>
  </LayoutTemplate>
 
  <ItemTemplate>
  <tr>
    <td>
      <%#Eval("Descrizione") %>
    </td>
  </tr>
  </ItemTemplate>
</asp:ListView>

A questo punto, tutto funziona correttamente: il controllo itemPlaceHolder viene sostituito a run-time con il contenuto esplcitato dell’ItemTemplate 🙂

Ovviamente, il valore della proprietà ID del componente asp:PlaceHolder dichiarato dentro il LayoutTemplate, è personalizzabile grazie all’attributo ItemPlaceholderID di ListView

Related Posts:

TSQL: leggere i tipi delle colonne di una tabella

Stavo ragionando sull’estender Fluent NHibernate per automatizzare il processo di produzione delle entità (sempre ammesso che non esista ancora nulla del genere).

Mi sono quindi posto il problema di come fare per leggere i tipi delle colonne di una tabella. Mi risponde Joe Webb sul suo blog:

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT 
   ORDINAL_POSITION
  ,COLUMN_NAME
  ,DATA_TYPE
  ,CHARACTER_MAXIMUM_LENGTH
  ,IS_NULLABLE
  ,COLUMN_DEFAULT
FROM   
  INFORMATION_SCHEMA.COLUMNS 
WHERE   
  TABLE_NAME = 'TABLE_NAME' 
ORDER BY 
  ORDINAL_POSITION ASC;

Related Posts:

Fluent NHibernate mapping exception: Association references unmapped class

Ieri ho perso metà pomeriggio di lavoro per una mia non conoscenza del mapping delle Entity in Fluent NHibernate.

L’eccezione lanciata da NHibernate:

1
Association references unmapped class: YourClass

Il mapping delle mie Entity avviene tramite un metoto CreateSessionFactory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
FluentNHibernate.Cfg.Fluently.Configure()
  .Database
    (
      FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
        .ConnectionString(
          c => c.Server(DbConnectionValue.Server)
                    .Username(DbConnectionValue.User)
                    .Password(DbConnectionValue.Password)
                    .Database(DbConnectionValue.Database)
          )
        .ProxyFactoryFactory("
NHibernate.ByteCode.LinFu.ProxyFactoryFactory
,NHibernate.ByteCode.LinFu")
  )
  .Mappings
  (
    m => m.FluentMappings
.AddFromAssemblyOf<OneClass.Of.My.Repository>()
  )
  .BuildSessionFactory();

Bisogna fare attenzione che esistono 2 regole affinchè si possa correttamente caricare il mapping di Entity caricate tramite il metodo AddFromAssemblyOf:

1. dichiarare sempre public le classi di mapping;
2. definire sempre le proprietà Id;

Related Posts:

Asp.net MVC JavaScriptSerializer: non serializzare proprietà automatich

Immaginiamo di avere il seguente modello:

1
2
3
4
5
6
7
8
 
public class MyModel
{
  public string Cognome { get; set; }
  public string Nome { get; set; }
 
  public DateTime DataNascita { get; set; }
}

Immaginiamo di utilizzare questo modello per renderizzare una View. Successivamente, questa ipotetica View restituirà in post lo stesso Modello.

Una delle scelte archiettturali che si può seguire, è quella di serializzare MyModel in JSon per poi passarlo al server. Ipotizziamo, adesso, di non voler serializzare una delle proprietà di MyModel, ad esempio DataNascita. Per farlo, basta agganciare alla proprietà DataNascita, l’attributo ScriptIgnore:

1
2
3
4
5
6
7
8
9
 
public class MyModel
{
  public string Cognome { get; set; }
  public string Nome { get; set; }
 
  [ScriptIgnore]
  public DateTime DataNascita { get; set; }
}

Related Posts:

C#: parametri ‘Specified’ nei servizi WCF

Ipotizziamo di avere questo contratto in un servizio WCF:

1
2
[OperationContract]
string HelloWorld(string foo, int bar);

Nel caso in cui ci si agganci da client non-WCF, come ad esempio client dotnet 1.1 (o client non dotnet), ci si potrebbe trovare in una situazione come la seguente:

1
2
Service1.HelloWorld(string foo, bool fooSpecified
, int bar, bool barSpecified);

L’ultimo parametro viene aggiunto per esplicitare l’obbligatorietà del parametro int bar. Questo comportamento nasce dall’assenza dei tipi nullable (int?, bool?) nei framework dotnet pre-2.0.

Per risolvere questa problematica:
1. aggiungere l’attributo XMLSerializerFormat come contratto all’interfaccia esposta dal web service WCF;
2. aggiungere l’attributo DataContract DataMember[IsRequired=true] alla proprietà da serializzare

Related Posts:

c#: stringhe e valori enums

Ultimamente mi sono ritrovato a dover fronteggiare un problema che, in realtà, è abbastanza comune.
Immaginiamo di avere un’area generica (diciamo un div) all’interno del quale restituiamo all’utente un messaggio a seconda della specifica funzionalità che deve eseguire.

Nell’ottica del riutilizzo del codice, potrebbe essere utile cambiare il messaggio visualizzato a seconda del punto dal quale si giunge.

Per questa ragione mi son chiesto se esistesse un modo per poter associare ad un enums uno specifico valore stringa. L’enums è sicuramente utile per individuare il punto dal quale si proviene, ma da solo non è sufficientemente potente per fornire un feedback all’utente.

Mai re-inventare la ruota, quando google ti può dare una mano 🙂
Stefan Sedich fornisce un’ottima soluzione al mio problema.

1. Definire un nuovo attributo custom di classe;

public class StringValueAttribute : Attribute
{
	public string StringValue { get; set; }
 
	public StringValueAttribute(string value)
	{
		this.StringValue = value;
	}
}

2. Creare un extension method il cui obiettivo sarà quello di recuperare il valore stringa dell’attributo StringValue associato ai singoli enums;

public static class StringValueExtension
{
    public static string GetStringValue(this Enum value)
    {
        type = value.GetType();
        fieldInfo = type.GetField(value.ToString());
 
  	StringValueAttribute[] attribs = 
        fieldInfo.GetCustomAttributes(
	   typeof(StringValueAttribute), false) 
           as StringValueAttribute[];
 
	return attribs.Length > 0 ? attribs[0].StringValue : null;
    }
}

3. Creare un enums con associato un attributo StringValue.

public enum Test : int 
{
    [StringValue("a")]
    EnumsA = 1,
 
    [StringValue("b")]
    EnumsB = 2        
}

Related Posts:

Asp.NET TextBox: attributo MaxLength in modalità MultiLine

Quando vi trovate ad utilizzare il componente asp:textbox in modalità multiline, noterete che l’attributo maxlength non funziona.

Non conosco ne conosco la ragione, però esiste un work-around:

private const int MAX_LENGTH = 100;
 
protected void Page_Load(object sender, EventArgs e)
{
string lengthFunction = "function isMaxLength(txtBox) {";
    lengthFunction += " if(txtBox) { ";
    lengthFunction += 
      "     return ( txtBox.value.length <=" + MAX_LENGTH + ");";
    lengthFunction += " }";
    lengthFunction += "}";
 
this.txtMyTextBox.Attributes.Add("onkeypress", 
      "return isMaxLength(this);");
      ClientScript.RegisterClientScriptBlock(
        this.GetType(), 
        "txtLength", 
        lengthFunction , true);
 
}

(via codegod.de)

Related Posts:

Asp.NET e Microsoft Reporting Services: ordinare una tabella Tablix da c#

In alcuni casi, nel realizzare un’applicazione web ha senso appoggiarsi a Microsoft Reporting Services per consentire agli utenti di stampare il risultato di una generica griglia sulla quale è possibile applicare un sorting.

Il problema è quello di riportare l’esatto sorting applicato sulla griglia anche sul report generato da Microsoft Reporting Services.

A tal fine, quindi, la strada che ho seguito è la seguente:

1. Creare due nuovi parametri all’interno del report: DIRECTION e SORTBY (parametri stringa con valore anche eguale a stringa vuota);

2. Entrare nelle proprietà della tabella Tablix, sezione ordinamento. Inserire le due seguenti espressioni:

=iif(Parameters!DIRECTION.Value="asc"
,Fields(Parameters!SORTBY.Value).Value,0)
=iif(Parameters!DIRECTION.Value="desc"
,Fields(Parameters!SORTBY.Value).Value,0)

Imporre che la prima sia un ordinamento “da A a Z” e la seconda un ordinamento “da Z ad A”

A questo punto è sufficiente impostare questi due parametri da codice c# ed il gioco è fatto 🙂

(via 15seconds.com)

Related Posts:

ASP.NET c# 3.5: cancellare il testo delle TextBox contenute nella pagina con LINQ

In rete esistono molti esempi di come si possa cancellare il testo contenuto nelle TextBox presenti nella propria pagina aspx.

Molti di questi esempi partono dal presupposto che la nostra pagina aspx non sia agganciata ad una masterpage. In questo caso, per la particolare gerarchia delle pagine aspx rispetto alla masterpage, bisogna apportare una piccola modifica al codice in questione.

Si deve infatti prima individuare il ContentPlaceHolder all’interno del quale insistono le TextBox di cui si vuole modificare la proprietà Text e successivamente utilizzare una lambda expression per eliminare il testo.

public void ClearTextBoxText()
{
ContentPlaceHolder mpContentPlaceHolder;
mpContentPlaceHolder = (ContentPlaceHolder)Master
                                 .("ContentPlaceHolder1");
 
if (mpContentPlaceHolder != null)
{
    List<TextBox> txt = mpContentPlaceHolder.Controls
                      .OfType<TextBox>()
                      .ToList()
                      .ForEach(t => t.Text = string.Empty);
}
}

Related Posts:

Visual Studio 2008 SP1 aggiornamento KB957912: perdita controllo durante il debug con F10 su applicazioni multi-threading

Quando si esegue un debug con F10 in Visual Studio 2008 nel contesto di applicazioni multi-threading, può succede che si perda il controllo dello stesso, emulando il comportamento del tasto F5.

Per risolvere il problema è necessario aggiornare la propria versione di Visual Studio, scaricando l’aggiornamento KB957912.

Il link alternativo si trova su code.msdn

Related Posts:

AspItalia Real Code Day 4 dicembre 2009 Firenze

Sono appena tornato dalla conferenza di ASPItalia “Real Code Day”, organizzata a Firenze nella struttura della Scuola Superiore Tecnologie Industriali (SSTI).

Tralascio l’organizzazione, appena sufficiente, considerati i problemi di rete e le continue sospensioni perchè dislocati in più aule collegate in wifi (numerosa partecipazione e, per dovere di cronaca, sentite scuse da parte di tutti anche di un tizio che credo sia il presidente/direttore/responsabile del SSTI.

Mi è piaciuta molto la disponibilità di Stefano Mostarda e Riccardo Golia al dialogo con tutti i partecipanti: una spanna sopra tutti.

Mi son piaciute molto meno le sessioni su WPF e Silverlight 4.0, troppo caciaroni e poco professionali gli speaker, il che, inevitabilmente, ha portato a disattenzione generale (soprattutto nelle aulee collegate in wireless) – una domanda su tutte: ma che ci frega di Silverlight e WPF e dello XAML, noi vogliamo vedere Blend (poi lo XAML ce lo leggiamo online).

Positivo il fatto che questa conferenza, come le altre due che ho seguito negli ultimi due mesi (ed organizzate direttamente da Microsoft), ti fanno tornare la passione di sviluppare applicazioni web di un certo livello e di approcciarsi al mondo dello sviluppo in un modo che non è per niente riscontrabile nella città di Roma (almeno nella mia diretta esperienza personale – spero esistano realtà diverse).

Related Posts:

Microsoft Visual Studio 2005: usare i dataset su SQL Server 2008

Per chi ancora nel 2009 si dovesse trovare ad utilizzare i dataset ed eventualmente in concomitanza con SQL Server 2008, potrebbe vedere questo errore in Visual Studio 2005, all’atto del tentativo di creazione di un TableAdapter:

“This server version is not supported. Only servers up to Microsoft SQL Server 2005 are supported.”

Per risolvere il problema, basta installare questa patch: VS80sp1-KB954961-X86-INTL

Grazie a Manuel per la segnalazione.

Related Posts:

C# Framework 3.5 Linq convert System.Collections.Generic.List<AnonymousType#1> to System.Collections.Generic.List<string>

L’obiettivo è la costruzione di un metodo (sia esso public, protected o private)
che ci consenta di estrarre una lista di stringhe.

La signature del nostro metodo sarà:

1
public List<string> getMyString()

Nel caso specifico vogliamo estrarre un set di dati rappresentati
da una e sola colonna di una tabella del nostro database.
Istintivamente, ci verrebbe da scrivere un pezzo di codice del tipo:

1
2
3
var q = from t in context.myentity
select new { Codice = t.mycodice };
List<string> listaCodici = q1.ToList();

Ovviamente è errato, sintatticamente e semanticamente.
Non è corretto supporre che, essendo il campo mycodice, un campo varchar, esso venga poi rimappato in un insieme di stringhe. Il compilatore, quindi, tornerà il seguente errore:

Cannot implicitly convert type
‘System.Collections.Generic.List<anonymoustype #1>’ to ‘System.Collections.Generic.List<string>’

Esistono due diverse strade per ottemperare al nostro obiettivo.
La prima è quella di definire una struct o una classe customizzata che contenga al suo interno la property, stringa, che andremo poi a valorizzare estraendo i dati dal database tramite LINQ.

La seconda è quella di scrivere un pezzo di codice come:

1
2
3
4
5
var q = from t in context.myentity
let codici = new { t.mycodice }
select codici;
List<string> listaCodici = (from c in q
select c.mycodice).ToList();

Related Posts:

C# 3.5 LINQ: restituire una lista tipizzata LIST<T>

Ipotizziamo di creare una solution in Visual Studio 2008 che strutturi
la nostra web application su n layer con un Object Model.
Il progetto Object Model conterrà l’Entity Model generato da VS2008.

Il DAL contiene, invece, il cuore dell’accesso ai dati: è nel DAL che
andremo a creare i metodi con le query LINQ per estrarre i dati secondo
le nostre esigenze.

L’obiettivo è quello di estrarre un sottoinsieme dei campi contenuti
nella tabella
, dalla quale VS2008 ha creato il modello delle Entity.

Chiamiamo AEntity l’entity definita nel modello.
Intuitivamente vorremmo scrivere un blocco di codice di questo tipo,
dove BaseDataAccess contiene la dichiarazione dell’oggetto context:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class DizionarioDataAccess : BaseDataAccess
{
    public List<objectmodel.AEntity> GetAll()
    {
       var items = from t in context.AEntity
                       select new
                       {
                           Nome = t.TABLE_NAME,
                           Cognome = t.TABLE_COGNOME
                       };
 
       return items.ToList<objectmodel.AEntity>();
    }

Il compilatore tornerà questo errore:

‘System.Linq.IQueryable<anonymoustype #1>’ does not contain a
definition for ‘ToList’ and the best extension method overload
‘System.Linq.Enumerable.ToList<tsource>
(System.Collections.Generic.IEnumerable<tsource>)’

has some invalid arguments

L’errore deriva dal fatto che con la direttiva select new, stiamo andando
a definire un nuovo oggetto che poco ha a che fare con l’Entity definita nel nostro modello.
Per risolvere il problema possiamo seguire due strade: o imponiamo che il
tipo tornato dal nostro metodo sia IQueryable, o creiamo un oggetto customizzato che abbia al suo
interno solo le proprietà che vogliamo valorizzare ed estrarre dal db.

Related Posts:

Microsoft .Net 3.5 Entity Framework WhitePaper

Documento vecchio, che ho avuto occasione di leggere solo oggi.

Un must per tutti gli sviluppatori che vogliono introdursi al Framework .Net 3.5

Related Posts:

C# specifiche: gli operatori condizionali

Noi sviluppatori spesso ci troviamo ad usare, per comodità, gli operatori condizionali (operatori condizionali in c#).

1
a = condizione ? prima_espressione : seconda_espressione;

In passato ho anche affrontato la teoria relativa ai tipi nullable, che ricordo essere dei tipi che accettano il valore null.

Oggi mi è capitato un errore compile-time che, a prima vista, potrebbe sembrare piuttosto banale:

Type of conditional expression cannot be determined because there is no implicit conversion between ‘‘ and ‘System.DateTime’

Spulciando le specifiche del linguaggio c#, ho scoperto un’interessante regola di base che, onestamente, non conoscevo.

Regola:
Ipotizziamo che X ed Y siano i tipi del secondo e terzo operando nell’espressione condizionale.
1. Se X ed Y sono dello stesso tipo, ne consegue che questo tipo è il tipo dell’espressione condizionale.
2. Nel caso in cui X ed Y siano diversi:
2a. se esiste una conversione implicita da X ad Y ma non da Y ad X, allora Y è il tipo dell’espressione condizionale;
2b. se esiste una conversione implicita da Y ad X, ma non da X ad Y, allora X è il tipo dell’espressione condizionale;
3. Nei restanti casi, non è possibile determinare il tipo dell’espressione per cui il compilatore ritorna un errore.

Esempio:

1
2
DateTime? nullableDate;  
nullableDate = (condition) ? null : DateTime.Now;

In questo caso X è null, per cui non c’è nessun tipo ad esso associabile. Nè tantomeno esiste un cast che ci dice che sia un null riferibile ad un qualche tipo specifico.

Non esiste nessuna conversione implicita da X (null) ad Y (DateTime).
Non esiste nessuna conversione implicita da Y (DateTime) ad X (null).

Secondo la regola, quindi, il compilatore deve tornare un errore.

Ovviare a questo problema è semplice: bisogna far capire al compilatore quale sia il tipo dell’espressione condizionale. Per farlo possiamo: fare un cast di entrambe le espressioni a DateTime?, oppure ancora fare un cast di null a DateTime? o, infine, fare un cast da DateTime a DateTime? (in questi ultimi due casi, esisterebbe una conversione implicita)

Related Posts: