2014-10-19 13 views
8

Sto lavorando a un'applicazione Web ASP.NET MVC 4. Sto usando Entity Framework come livello di accesso ai dati, usando il primo approccio al database (file .edmx).Unione di tabelle da due database utilizzando il framework di entità

Attualmente ho un problema nelle tabelle di join che sono definite all'interno di due database diversi (ad esempio, ho due file .edmx).

Per esempio se voglio unire le tabelle che sto eseguendo la seguente query: -

public ActionResult AutoComplete(string term) 
{ 
    var tech = repository.AllFindTechnolog(term).Take(100);//Call to the first database 
    var resources = repository.GetResources(tech.Select(a => a.IT360ID.Value).ToArray(), false);//call to the second database 

    var query = from techItems in tech 
     join resourcesItems in resources 
     on techItems.IT360ID.Value equals resourcesItems.RESOURCEID // join based on db2ID 
     orderby techItems.PartialTag 
     select new //code goes here 

    return Json(query, JsonRequestBehavior.AllowGet); 
} 

avrò due chiamate separate al database, e un join all'interno del server di applicazione, che non è il migliore soluzione orientata alla prestazione. Idealmente i join avverranno completamente all'interno del motore del database.

So che una stored procedure mi consentirà di unire tabelle da database diversi esclusivamente sul server, ma non voglio utilizzare SP perché renderà il mio codice meno gestibile e meno controllabile.

Quindi sto cercando una soluzione in cui posso fare il join usando il framework di entità e creare un singolo join di database?

+0

L'idea principale è che abbiamo scelto di lavorare con Entity Framework come nostro livello di accesso ai dati è che fornisce le seguenti caratteristiche principali: - 1. Il codice di accesso ai dati siano rispettate e testati come parte del tutto applicazione. più testabile e offre tempi di sviluppo rapidi confrontando le stored procedure.2, EF fornisce un livello sopra il database e il nostro prodotto può funzionare su diversi fornitori di database. e come ho già detto che l'unica funzionalità attualmente disponibile che dipende direttamente dal database è una procedura memorizzata per eseguire la ricerca avanzata –

+0

ma se voglio iniziare a creare viste per diverse funzionalità, allora perderò i vantaggi offerti da EF. quindi fammi ricostruire la mia domanda originale è il mio attuale approccio di recuperare i dati relativi dai due database utilizzando due istruzioni SQL separate e quindi unire i dati sul server delle applicazioni considerato un design molto cattivo? Anche se avrò due query separate ma sono meno costose rispetto a una singola istruzione sql join ... –

+0

Potrei avere una soluzione per te, ma ho una domanda: cosa stai selezionando nella tua variabile 'query'? Stai prendendo dati da entrambi i contesti, o solo da uno di essi (ad esempio, prendi solo gli elementi in 'tech' che esistono in' risorse')? – IronMan84

risposta

0

Potrei suggerire di esaminare l'utilizzo di synonym nel database. Ad esempio, è possibile creare un sinonimo per la tabella delle risorse nel database in cui si trova la tabella tecnologica. Ciò garantirà che non sarà necessario mantenere 2 file EDMX. Invece puoi avere un singolo file EDMX e puoi semplicemente unire il tuo tavolo tecnico al sinonimo della tabella delle risorse e voilà - sei sulla buona strada.

AGGIORNAMENTO: Si noti che se si utilizzano sinonimi, è necessario un ulteriore lavoro da svolgere sul file EDMX per farlo funzionare in Entity Framework. Ecco uno blog post che è stato messo fuori da un programmatore che l'ha fatto funzionare. Ecco la domanda originale stackoverflow che ha chiesto.

CODICE FELICE !!! :)

+0

quello che stavo cercando è un approccio più immediato per supportare l'unione di tabelle all'interno del DB, da due diversi database utilizzando il framework di entità. –

+0

@johnG - Non è possibile unire le due tabelle di database in due diversi contesti senza facendo ciò che stai facendo attualmente, che sta selezionando ognuno di essi e aggiungendo i risultati. L'unico modo che puoi fare è se entrambe le tabelle vengono selezionate nello stesso contesto in qualche modo - che è dove entra in gioco l'uso di un sinonimo. – Gjohn

+0

così farà il join all'interno del mio server delle applicazioni e passerà due query di database a ciascun database considerato un pessimo design? Voglio dire, ci sono situazioni reali in cui questo tipo di limitazione viene risolta eseguendo soluzioni simili? –

3

Se si desidera eseguire una chiamata al database, è necessario creare una vista nel database che unisce le due tabelle da db separati. Una volta creata la vista, puoi aggiungerla a EF come un singolo oggetto, che puoi manipolare ulteriormente e Interrompere. La vista sarà fondamentalmente una tabella e sarà facilmente eseguibile e facilmente associabile a un modello fortemente tipizzato

Un altro modo, come quello che hai pubblicato, puoi interrogare separati i file .edmx e poi unirti a loro. Sì, ci sono 2 chiamate al database ma non dovrebbe essere così costoso e probabilmente non noterà alcuna differenza.

using(var db = new MyEntities()) 
using (var db2 = new MyEntities2()) 
{ 
    var one = db.Table1.AsEnumerable(); 
    var two = db2.Table2.AsEnumerable(); 

    var result = from o in one 
       join t in two on o.Id equals t.Id 
       // blah blah 

} 
+3

Ma per evitare un'eccezione EF che dice che non è possibile utilizzare due contesti in una query, si dovrebbe fare 'db.Table1.AsEnumerable()' e 'db2.Table2.AsEnumerable()'. –

+4

Un'ottima idea a mio avviso: ogni volta che si chiama "AsEnumerable()" su una tabella, EF recupererà l'intero contenuto della tabella e lo caricherà nella RAM. –

1

@ La risposta di CSharper è vicina. Come @Oliver menzionato nei commenti, IEnumerable carica la tabella nella memoria dell'applicazione, causando arresti anomali se si dispone di un database di grandi dimensioni.

La soluzione è utilizzare IQueryable, che può essere chiamato con LINQ - questo produce SQL che è molto più veloce.

// This is a generic method, modify to your needs 
public ActionResult Details(int? id) 
    var one = db.Table1.AsQueryable(); 
    var two = db2.Table2.AsQueryable(); 

    // since you're using MVC EF, I assume you want to put this in a viewmodel 
    // (in this case ObjectCombined) 
    // assume "id" is passed as parameter 
    Object1 result1 = (from o in one where one.id == id select o).Single(); 
    Object2 result2 = (from t in two where t.id == o.id select t).Single(); 
    ObjectCombined result = new ObjectCombined(result1, result2); 
    return View(result); 
}