2011-12-20 11 views
5

Diciamo che abbiamo un progetto che gestirà molti dati (impiegati, calendari, calendari .... e molto altro). Il client è Windows App, il lato server è WCF. Il database è MS SQL Server. Sono confuso su quale approccio usare. Ho letto alcuni articoli e blog che sembrano tutti carini, ma sono confuso. Non voglio iniziare con un approccio e poi rimpiango di non aver scelto l'altro. Il progetto avrà circa 30-35 tipi di oggetti diversi. Un sacco di dati recupero per popolare diverse relazioni ... eccquale design è migliore per un progetto client/server con molta condivisione dei dati

Approccio 1:

// classes that hold data 

public class Employee 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    ..... 
} 

public class Assignment 
{ 
    public int Id { get; set; } 
    public int UserId { get; set; } 
    public DateTime Date { get; set; } 
    ..... 
} 
..... 

classi Poi Helper per affrontare il salvataggio e il recupero dei dati:

public static class Employees 
{ 
    public static int Save(Employee emp) 
    { 
     // save the employee 
    } 

    public static Employee Get(int empId) 
    { 
     // return the ugly employee 
    } 
    ..... 
} 

public static class Assignments 
{ 
    public static int Save(Assignment ass) 
    { 
     // save the Assignment 
    } 
    ..... 
} 

saluti, il le classi di oggetti come Dipendenti e Assegnazione si troveranno in un Assemblaggio separato da condividere tra Sever e Client. Ad ogni modo, con questo approccio avrò un oggetto più pulito. Le classi Helper faranno la maggior parte del lavoro.

Approccio 2:

// classes that hold data and methods for saving and retrieving 

public class Employee 
{ 
    // constructors 
    public Employee() 
    { 
     // Construct a new Employee 
    } 
    public Employee(int Id) 
    { 
     // Construct a new Employee and fills the data from db 
    } 

    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    ..... 

    public int Save() 
    { 
     // save the Employee 
    } 
    ..... 
} 

public class Assignment 
{ 
    // constructors 
    public Assignment() 
    { 
     // Construct a new assignment 
    } 
    public Assignment(int Id) 
    { 
     // Construct a new assignment and fills the data from db 
    } 

    public int Id { get; set; } 
    public int UserId { get; set; } 
    public DateTime Date { get; set; } 
    ..... 

    public int Save() 
    { 
     // save the Assignment 
    } 
    ..... 
} 
..... 

Con questo approccio, ogni oggetto farà il suo lavoro .. I dati ancora può essere trasferito da WCF per cliente facilmente dal WCF solo le proprietà delle azioni.

Approccio 3:

Utilizzando Entity Framework .. oltre al fatto che non ho mai lavorato con lui (che è bello perché devo imparare qualcosa di nuovo) ho bisogno di creare pocos per trasferire i dati tra client e WCF ..

Ora, qual è il migliore? più opzioni?

+0

Una buona domanda, ma forse una soluzione migliore per i programmatori. – jwiscarson

risposta

0

Suggerisco di utilizzare il modello Entity Framework + Repository. In questo modo le tue entità sono oggetti semplici senza alcuna logica in essi. Tutta la logica di recupero/recupero rimane nel repository. Ho una certa esperienza con l'utilizzo di repository generico, che viene digitato con entità, qualcosa di simile è descritto here (parte repository generico dell'articolo). In questo modo scrivi il codice del repository una sola volta e puoi riutilizzarlo per tutte le entità che hai. Ad esempio:

interface IRepositry<T> 
{ 
T GetById(long id); 
bool Save(T entity); 
} 

public class Repository<T> : IRepository<T> {...} 

var repository = new Repository<MyEntity>(); 
var myEntity = repository.GetById(1); 
var repository2 = new Repository<MySecondEntity>(); 
var mySecondEntity = repository.GetById(1); 

Ogni volta che un soggetto ha bisogno di qualche operazione molto specifica, è possibile aggiungere questa operazione per un concreto digitato implementazione di IRepository:

interface IMySuperRepositry : IRepository<MySuperEntity> 
{ 
    MySuperEntity GetBySuperProperty(SuperProperty superProperty); 
} 

public class MySuperEntityRepository : Repository, IMySuperRepository 
{...} 

Per creare repository è piacevole da usare una fabbrica, che è basato per esempio sul file di configurazione. In questo modo puoi cambiare l'implementazione dei repository, ad es. per unit testing, quando non si desidera utilizzare repository che in realtà accede DB:

public class RepositoryFactory 
{ 
    IRepository<T> GetRepository<T>() 
{ 
    if (config == production) 
    return new Repository<T>(); // this is implemented with DB access through EF 
    if (config == test) 
    return new TestRepository<T>(); // this is implemented with test values without DB access 
} 
} 

}}

È possibile aggiungere regole di convalida per il salvataggio e l'ulteriore elaborato su questo. EF consente inoltre di aggiungere alcuni semplici metodi o proprietà alle entità generate, poiché tutte sono classi parziali.

Inoltre, utilizzando POCO o STE (vedere più avanti) è possibile avere il modello EDMX DB in un progetto e tutte le entità in un altro progetto e quindi distribuire questa DLL al client (che conterrà SOLO le proprie entità). Come ho capito, è quello che vuoi anche ottenere.

Considerare anche seriamente l'utilizzo di Self tracking entities (e non solo POCO). Secondo me sono ottimi per l'utilizzo con WCF. Quando si ottiene un'entità dal DB e lo si passa al client, il client lo modifica e lo restituisce, è necessario sapere se l'entità è stata modificata e cosa è stato modificato. STE gestisce tutto questo lavoro per te e sono progettati specificamente per WCF. Ottieni entità dal client, ad esempio ApplyChanges e Save, il gioco è fatto.

0

Che ne pensi di implementare il metodo Salva come estensione? In questo modo le classi sono pulite come nella prima opzione, ma i metodi possono essere richiamati sull'oggetto come nella seconda opzione.

public static class Employee 
{ 
    public static int Save(this Employee emp) 
    { 
     // save the employee 
    } 

    public static Employee Get(int empId) 
    { 
     // return the ugly employee 
    } 

} 
2

Avere la logica di peristenza nell'oggetto stesso è sempre una cattiva idea.

Vorrei utilizzare il primo approccio. Sembra Repository pattern. In questo modo, puoi facilmente eseguire il debug del perist dei dati, perché sarà chiaramente separato dal resto della logica dell'oggetto.

0

stai pensando questo. provare ad applicare tecnologie e modelli "solo perché" o "questo è quello che dicono" rende la soluzione complicata. La chiave sta progettando l'applicazione in modo che possa adattarsi facilmente ai cambiamenti. questa è probabilmente una risposta ambigua, ma è quello a cui tutto si riduce. quanto sforzo è necessario per mantenere e/o modificare il codice base.

al momento sembra che i modelli e le pratiche sono il risultato finale, invece di un mezzo per un fine.

+0

Ho intenzione di pensarci sopra .. Pensare non è di solito cattivo.Porta a imparare cose nuove. In ogni modo il tuo punto sullo sforzo richiesto per mantenere il codice è il punto principale .. ma provare ancora qualcosa di nuovo è un punto anche .. –

0

Entity Framework è un ottimo strumento ma non è necessariamente la scelta migliore in tutti i casi. Dipenderà da quanto ti aspetti di leggere/scrivere dal database rispetto a quanto ti aspetti di leggere/scrivere sui tuoi servizi WCF. Forse qualcuno esperto nel meraviglioso mondo di EF sarà in grado di aiutarti.Per parlare per esperienza, ho usato LINQ-TO-SQL in un'applicazione che presenta gli endpoint del servizio WCF e non ha avuto problemi (e in effetti è venuto a AMARE Linq-To-Sql come un ORM).

Detto questo, se decidi che EF non è la scelta giusta per te, sembra che tu sia sulla strada giusta con Approach 1. Tuttavia, suggerirei di implementare uno DataAccessLayer. Vale a dire, implementare un metodo nelle classi di business che chiama i metodi in un DAO separato (oggetto di accesso ai dati o una classe utilizzata per mantenere i dati da un oggetto business) per salvarlo effettivamente nel database.

Un esempio di implementazione potrebbe essere simile a questo:

public class Employee 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    public void Persist() 
    { 
     EmployeeDAO.Persist(this); 
    } 
} 

public class Assignment 
{ 
    public int Id { get; set; } 
    public int UserId { get; set; } 
    public DateTime Date { get; set; } 

    public void Persist() 
    { 
     AssignmentDAO.Persist(this); 
    } 
} 

public static class EmployeeDAO 
{ 
    public static int Persist(Employee emp) 
    { 
     // insert if new, else update 
    } 

    public static Employee Get(int empId) 
    { 
     // return the ugly employee 
    } 
    ..... 
} 

public static class AssignmentDAO 
{ 
    public static int Persist(Assignment ass) 
    { 
     // insert if new, else update 
    } 
    ..... 
} 

Il vantaggio di un modello come questo è che si arriva a mantenere le vostre classi di business pulito, la logica di accesso ai dati separati, mentre continua a fornire gli oggetti i sintassi facile di essere in grado di scrivere new Employee(...).Persist(); nel codice.

Se davvero si vuole andare noci, si potrebbe anche prendere in considerazione le interfacce di esecuzione riguardante i tuoi Persistable classi, e hanno il DAO (s) accettare quelle IPersistable casi come argomenti.

+0

Il tuo approccio è bello, sembra "Approccio 1" e "Approach 2" si sono sposati e hanno avuto il tuo approccio da bambino .. aspetterò più opzioni e opinioni .. –

Problemi correlati