Domanda

Questa domanda non mi lascia dormire in quanto è da un anno che sto cercando di trovare una soluzione, ma ... ancora non è successo niente nella mia mente. Probabilmente che mi può aiutare, perché credo che questo è un problema molto comune.

ho un n-strati di applicazione: livello di presentazione, livello di logica di business, livello di modello. Supponiamo per semplicità che la mia applicazione contiene, il livello di presentazione, una forma che consente a un utente per la ricerca di un cliente. Ora l'utente riempie i filtri tramite l'interfaccia utente e il clic su un pulsante. Qualcosa accade e la richiesta arriva a livello di presentazione ad un metodo come CustomerSearch(CustomerFilter myFilter). Questo strato logica di business la società mantiene semplice: crea una query sul modello e torna risultati.

Ora la domanda: come si fa a affrontare il problema di caricamento dei dati? Voglio dire livello di logica di business non sa che quel particolare metodo verrà richiamato solo con quella forma. Quindi penso che non sa se il modulo di richiesta deve solo gli oggetti del Cliente schiena o oggetti al Cliente con le entità Order collegate.

Provo a spiegarmi meglio: il nostro modulo vuole solo I clienti alla ricerca per cognome. Non ha nulla a che fare con gli ordini. Quindi la domanda logica di business sarà qualcosa di simile:

(from c in ctx.CustomerSet
where c.Name.Contains(strQry) select c).ToList();

Ora, questo funziona correttamente. Due giorni dopo il tuo capo ti chiede di aggiungere un modulo che consente di cercare per clienti come l'altro ed è necessario mostrare il conteggio totale degli ordini creati da ciascun cliente. Ora mi piacerebbe riutilizzare quel query e aggiungere il pezzo di logica che si attaccano ( include ) gli ordini e si rimette così.

Come faresti fronte a questa richiesta?

Questa è la migliore (credo) idea che avevo fin da ora. Mi piacerebbe sentire da voi: il mio metodo CustomerSearch in BLL non crea la query direttamente, ma passa attraverso metodi di estensione private che compongono l'ObjectQuery come:

private ObjectQuery<Customer> SearchCustomers(this ObjectQuery<Customer> qry, CustomerFilter myFilter)

e

private ObjectQuery<Customer> IncludeOrders(this ObjectQuery<Customer> qry)

, ma questo non mi convince come sembra troppo complesso.

Grazie, Marco

È stato utile?

Soluzione

Si consideri trasferirsi in DTO per l'interfaccia tra il livello di presentazione e lo strato di business, si veda ad esempio: - http://msdn.microsoft.com/en-us/magazine/ee236638.aspx

Qualcosa di simile Automapper può alleviare gran parte del dolore associato con lo spostamento al DTOs e la mossa farà quello esplicito che si può e non può fare con i risultati di una query, vale a dire se è sul DTO è caricato, se non lo è è necessario un DTO diversa.

Il tuo attuale piano suona un po 'troppo strettamente accoppiati tra il livello di presentazione e lo strato di dati.

Altri suggerimenti

Sono d'accordo con il commento da Hightechrider in riferimento utilizzando DTOS, tuttavia avete una domanda valida per quanto riguarda le entità di business.

Una possibile soluzione (sto usando qualcosa in questo senso su un progetto che sto sviluppando) è quello di utilizzare DTOS che sono di sola lettura (almeno dal punto di vista livello di presentazione. Vostri criteri / ottenere operazioni sarebbe tornato solo DTOS , questo darebbe la possibilità lazy loading.

Si potrebbe impostare il livello di business per restituire un oggetto modificabile che avvolge il DTO quando un oggetto / soggetto viene aggiornato / creato. Il vostro oggetto modificabile potrebbe far rispettare le regole di business e poi quando è stato salvato / passata al livello di business il DTO è avvolto (con i valori aggiornati) potrebbe essere passata al livello dei dati.

public class Editable
{
    //.......initialize this, other properties/methods....

    public bool CanEdit<TRet>(Expression<Func<Dto, TRet>> property)
    {
        //do something to determine can edit
        return true;
    }

    public bool Update<TRet>(Expression<Func<Dto, TRet>> property, TRet updatedValue)
    {
        if (CanEdit(property))
        {
            //set the value on the property of the DTO (somehow)
            return true;
        }
        return false;
    }

    public Dto ValueOf { get; private set;}
}

Questo ti dà la possibilità di far valere se l'utente può ottenere oggetti modificabili dal livello di business oltre a permettere l'oggetto di business per far rispettare se l'utente ha il permesso di modificare le proprietà specifiche di un oggetto. Un problema comune mi imbatto in con il lavoro di dominio io in è che alcuni utenti possono modificare tutte le proprietà e gli altri non possono, mentre chiunque può visualizzare i valori delle proprietà. Inoltre il livello di presentazione acquisisce la capacità di determinare quali di esporre come modificabili per l'utente come dettato e imposto dal livello di business.

Altro pensiero che ho avuto è il vostro livello di business non può esporre IQueryable o prendere le espressioni standard come argomenti che vengono passati al vostro livello di dati. Per esempio io ho un qualcosa di query pagina di edificio come questo:

public class PageData
{
    public int PageNum;
    public int TotalNumberPages;
    public IEnumerable<Dto> DataSet;
}

public class BL
{
    public PageData GetPagedData(int pageNum, int itemsPerPage, Expression<Func<Dto, bool>> whereClause)
    {
        var dataCt = dataContext.Dtos.Where(whereClause).Count();
        var dataSet = dataContext.Dtos.Where(whereClause).Skip(pageNum * itemsPerPage).Take(itemsPerPage);

        var ret = new PageData
                        { 
                          //init this
                        };

        return ret;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top