2009-05-22 12 views
16

Ecco il problema:Simulazione di join incrociati di contesto - LINQ/C#

Ho due contesti di dati su cui vorrei fare un join. Ora so che LINQ non consente l'accesso da un contesto a un altro, e so che 2 possibili soluzioni potrebbero essere creare un singolo datacontext o avere 2 query separate (che è ciò che sto facendo per ora). Comunque quello che vorrei fare è "simulare" un join.

Ecco cosa ho provato.

using (var _baseDataContext = Instance) 
{ 
    var query = from a in _baseDataContext.Account.ACCOUNTs 
       where a.STR_ACCOUNT_NUMBER.ToString() == accountID 
       join app in _baseDataContext.Account.APPLICATIONs on a.GUID_ACCOUNT_ID equals 
          app.GUID_ACCOUNT 
       join l in GetLoans() on app.GUID_APPLICATION equals l.GUID_APPLICATION 
       select l.GUID_LOAN; 

    return query.Count() > 0 ? query.First() : Guid.Empty; 
} 

private static IQueryable<LOAN> GetLoans() 
{ 
    using (var _baseDataContext = Instance) 
    { 
     return (from l in _baseDataContext.Loan.LOANs 
       select l).AsQueryable(); 
    } 
} 

In fase di esecuzione che ottenga è

System.InvalidOperationException: La query contiene riferimenti a oggetti definiti in un diverso contesto dati

EDIT:

soluzione di lavoro:

using (var _baseDataContext = Instance) 
{ 
    var query = from a in _baseDataContext.Account.ACCOUNTs 
       where a.STR_ACCOUNT_NUMBER.ToString() == accountID 
       join app in _baseDataContext.Account.APPLICATIONs on a.GUID_ACCOUNT_ID equals 
          app.GUID_ACCOUNT 
       join l in GetLoans() on app.GUID_APPLICATION equals l.GUID_APPLICATION 
       select l.GUID_LOAN; 

    return (query.Count() > 0) ? query.First() : Guid.Empty; 
} 

private static IEnumerable<LOAN> GetLoans() 
{ 
    using (var _baseDataContext = Instance) 
    { 
     return (from l in _baseDataContext.Loan.LOANs 
       select l).AsQueryable(); 
    } 
} 

risposta

12

Forse qualcosa del genere può farti iniziare nella giusta direzione. Ho creato un database fittizio con colonne simili in base ai nomi delle colonne e ottenuto alcuni risultati.

class Program 
{ 
    static AccountContextDataContext aContext = new AccountContextDataContext(@"Data Source=;Initial Catalog=;Integrated Security=True"); 
    static LoanContextDataContext lContext = new LoanContextDataContext(@"Data Source=;Initial Catalog=;Integrated Security=True"); 

    static void Main() 
    { 

     var query = from a in aContext.ACCOUNTs 
        join app in aContext.APPLICATIONs on a.GUID_ACCOUNT_ID equals app.GUID_ACCOUNT 
        where app.GUID_APPLICATION.ToString() == "24551D72-D4C2-428B-84BA-5837A25D8CF6" 
        select GetLoans(app.GUID_APPLICATION); 

     IEnumerable<LOAN> loan = query.First(); 
     foreach (LOAN enumerable in loan) 
     { 
      Console.WriteLine(enumerable.GUID_LOAN); 
     } 

     Console.ReadLine(); 
    } 

    private static IEnumerable<LOAN> GetLoans(Guid applicationGuid) 
    { 
     return (from l in lContext.LOANs where l.GUID_APPLICATION == applicationGuid select l).AsQueryable(); 
    } 
} 

Spero che questo aiuti!

+0

Ho provato a restituire IEnumerable in precedenza, ma ho ricevuto un errore di trasmissione come previsto. Tuttavia non avevo pensato di restituire un IEnuerable AsQueryable. –

+0

un potenziale problema con questo approccio è che non stai facendo un puro join, quindi se hai bisogno di aggiungere un altro join dal contesto del prestito non sarai in grado di vedere da quello che posso vedere. –

+0

Okay ha funzionato. Siamo in grado di rimuovere la clausola where sul join del metodo e invece di eseguire una selezione dal metodo, è sufficiente eseguire un join puro.Il trucco qui è che il metodo deve restituire un oggetto IEnumerable . AsQueryable Ciò ci consente di eseguire join incrociati di contesto, e fino ad ora non vedo alcun risultato in termini di prestazioni. –

0

Io preferisco creare un contesto dati separato che contenga ns solo i due tavoli che vuoi unire. Ma suppongo che potresti mantenere una tabella temporanea (contenente i dati dal primo contesto) nel secondo contesto e quindi unirti alla tabella temporanea.

+0

creare un datacontext separato in cui è sufficiente disporre delle due tabelle è una possibilità, tuttavia questo non è un bisogno isolato, è solo un esempio di una necessità per questa soluzione. Voglio evitare di creare un datacontext isolato ogni volta che ho bisogno di soddisfare questa esigenza. –

3

Questo è il "lavoro intorno" che abbiamo trovato ...

abbiamo costruito la nostra tabelle dall'altro database manualmente fuori e se è sullo stesso server poi ci prefisso il nome della tabella con:

<DatabaseName>.<SchemaName>.<YourTableName> 

se sono su un server collegato poi si deve prefisso con il nome del server così:

<ServerName>.<DatabaseName>.<SchemaName>.<YourTableName> 

Questo vi permetterà di fare unisce ed ancora restituite un io non eseguita Queryable ... che è quello che volevamo. Gli altri 2 modi in coinvolgono unire in memoria IEnumerables che significa il tuo tirare tutti i record per ciascuno prima di fare il join (sopra) e fare un join IQueryable utilizzando un metodo contiene che ha limitazioni ...

Speriamo che in futuro il DataContext sarà costruito in modo sufficientemente intelligente da sapere che se i server sono collegati, puoi fare join tra due diversi.

+0

Anche se è una buona idea, in questo caso non è un'opzione. Grazie per il suggerimento comunque. –