Domanda

Ora che LINQ to SQL è un file poco più maturo, mi piacerebbe conoscere eventuali tecniche che le persone utilizzano per creare una soluzione a più livelli utilizzando la tecnologia, perché non mi sembra così ovvio.

È stato utile?

Soluzione

LINQ to SQL non ha in realtà una storia a più livelli che ho visto, dal momento che gli oggetti che crea vengono creati nella classe con il resto, non hai davvero un assembly a cui puoi fare riferimento facilmente qualcosa come servizi Web, ecc.

L'unico modo in cui lo considererei davvero è utilizzare il contesto dei dati per recuperare i dati, quindi riempire un modello di dati intermedio, passandolo e facendovi riferimento su entrambi i lati e utilizzandolo sul lato client, quindi restituendoli e spingendo il i dati in un nuovo Datacontext o aggiornando in modo intelligente le righe dopo averle recuperate.

Questo se ho capito cosa stai cercando di ottenere:\

Ho posto la stessa domanda a ScottGu sul suo blog quando ho iniziato a esaminarlo, ma non ho visto un singolo scenario o app in circolazione che utilizzi LINQ to SQL in questo modo.Siti web come Storefront di Rob Connery sono più vicini al fornitore.

Altri suggerimenti

Hmm, Rockford Lhotka triste, che LINQ to SQL sia una tecnologia meravigliosa per recuperare dati dal database.Suggerisce che in seguito dovranno essere vincolati per "raggiungere gli oggetti del dominio" (aka.oggetti CSLA).

Seriamente parlando, LINQ to SQL aveva il supporto per l'architettura a più livelli DataContext.Update metodo.

Potresti voler esaminare il ADO .Net Entity Framework come alternativa a LINQ to SQL, sebbene supporti anche LINQ.Credo che LINQ to SQL sia progettato per essere abbastanza leggero e semplice, mentre Entity Framework è più pesante e probabilmente più adatto alle applicazioni aziendali di grandi dimensioni.

OK, mi darò una possibile soluzione.

Gli inserti/aggiornamenti non sono mai stati un problema;puoi racchiudere la logica aziendale in un metodo di salvataggio/aggiornamento;per esempio.

public class EmployeesDAL
{
    ...
    SaveEmployee(Employee employee)
    {
        //data formatting
        employee.FirstName = employee.FirstName.Trim();
        employee.LastName = employee.LastName.Trim();

        //business rules
        if(employee.FirstName.Length > 0 && employee.LastName.Length > 0)
        {
            MyCompanyContext context = new MyCompanyContext();

            //insert
            if(employee.empid == 0)
             context.Employees.InsertOnSubmit(employee);
            else
            {
              //update goes here
            }

            context.SubmitChanges();


        }
        else 
          throw new BusinessRuleException("Employees must have first and last names");
     }
 }

Per recuperare i dati, o almeno il recupero di dati provenienti da più di una tabella, è possibile utilizzare procedure o viste memorizzate perché i risultati non saranno anonimi, quindi è possibile restituirli da un metodo esterno.Ad esempio, utilizzando una procedura memorizzata:

    public ISingleResult<GetEmployeesAndManagersResult> LoadEmployeesAndManagers()
    {
        MyCompanyContext context = new MyCompanyContext();

        var emps = context.GetEmployeesAndManagers();

        return emps;
    }

Scherzi a parte, LINQ to SQL aveva il supporto per l'architettura a più livelli, vedere il metodo DataContext.Update

Parte di ciò che ho letto suggerisce che la logica aziendale racchiude DataContext, in altre parole si avvolge l'aggiornamento nel modo suggerito.

Nel modo in cui tradizionalmente scrivo oggetti business, di solito incapsulano anche i "metodi di caricamento" nel BO;quindi potrei avere un metodo chiamato LoadEmployeesAndManagers che restituisce un elenco di dipendenti e dei loro diretti manager (questo è un esempio inventato).Forse sono solo io, ma nel mio front-end preferirei vedere e.LoadEmployeesAndManagers() piuttosto che una lunga istruzione LINQ.

Ad ogni modo, usando LINQ probabilmente sarebbe simile a questo (non verificata la correttezza della sintassi):

var emps = from e in Employees
                join m in Employees
                on e.ManagerEmpID equals m.EmpID
                select new
                          { e,
                            m.FullName
                          };

Ora, se ho capito bene le cose, se lo inserisco, ad esempio, in una libreria di classi e lo chiamo dal mio front-end, l'unico modo in cui posso restituirlo è come IEnumerable, quindi perdo la mia forte bontà digitata.L'unico modo in cui potrei restituire un oggetto fortemente tipizzato sarebbe creare la mia classe Employees (più un campo stringa per il nome del manager) e riempirla con i risultati della mia istruzione LINQ to SQL e quindi restituirla.Ma questo sembra controintuitivo...cosa mi ha comprato esattamente LINQ to SQL se devo fare tutto questo?

Penso che potrei guardare le cose nel modo sbagliato;qualsiasi illuminazione sarebbe apprezzata.

"l'unico modo in cui posso restituirlo è come IEnumerable, quindi perdo la mia forte bontà digitata"

questo non è corretto.In effetti la tua query è fortemente tipizzata, è solo di tipo anonimo.Penso che la query che desideri sia più simile a:

var emps = from e in Employees
            join m in Employees
            on e.ManagerEmpID equals m.EmpID
            select new Employee
                      { e,
                        m.FullName
                      };

Che restituirà IEnumerable.

Qui è un articolo Ho scritto sull'argomento.

Linq-to-sql è un ORM.Non influisce sul modo in cui si progetta un'applicazione a più livelli.Lo usi nello stesso modo in cui utilizzeresti qualsiasi altro ORM.

@liammclennan

Che restituirà IEnumerable....Linq-to-sql è un ORM.Non influisce sul modo in cui si progetta un'applicazione a più livelli.Lo usi nello stesso modo in cui utilizzeresti qualsiasi altro ORM.

Allora immagino di essere ancora confuso.Sì, Linq-to-Sql è un ORM;ma per quanto ne so sto ancora riempiendo il mio codice front-end con istruzioni di tipo SQL in linea (linq, non sql....ma ritengo comunque che questo dovrebbe essere astratto dal front-end).

Supponiamo di racchiudere l'istruzione LINQ che abbiamo utilizzato come esempio in un metodo.Per quanto ne so, l'unico modo per restituirlo è questo:

public class EmployeesDAL
{
    public IEnumerable LoadEmployeesAndManagers()
    {
            MyCompanyContext context = new MyCompanyContext();

            var emps = from e in context.Employees
            join m in context.Employees
            on e.ManagerEmpID equals m.EmpID
            select new
                      { e,
                        m.FullName
                      };

            return emps;
    }

}

Dal mio codice front-end farei qualcosa del genere:

EmployeesDAL dal = new EmployeesDAL;
var emps = dal.LoadEmployeesAndManagers();

Questo ovviamente restituisce un IEnumerable;ma non posso usarlo come qualsiasi altro ORM come dici tu (a meno che ovviamente non fraintenda), perché non posso farlo (di nuovo, questo è un esempio artificioso):

txtEmployeeName.Text = emps[0].FullName

Questo è quello che intendevo per "perdo una forte bontà tipizzata". Penso che sto iniziando a essere d'accordo con il crogiolo;che LINQ-to-SQL non è stato progettato per essere utilizzato in questo modo.Ancora una volta, se non vedo le cose correttamente, qualcuno mi mostri la strada :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top