2009-05-22 17 views
16

Aquí está el problema:Cruz se une Contexto - LINQ/C#

tengo 2 contextos de datos que me gustaría hacer una combinación en. Ahora sé que LINQ no permite uniones de un contexto a otro, y sé que 2 posibles soluciones serían crear un solo contexto de datos o tener 2 consultas separadas (que es lo que estoy haciendo por ahora). Sin embargo, lo que me gustaría hacer es "simular" una unión.

Esto es lo que he intentado.

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(); 
    } 
} 

En tiempo de ejecución lo que consigo es

System.InvalidOperationException: La consulta contiene referencias a elementos definidos en un contexto de datos diferente

EDIT:

Solución de Trabajo

:

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(); 
    } 
} 

Respuesta

12

Tal vez algo como esto puede ayudarlo a comenzar en la dirección correcta. Hice una base de datos simulada con columnas similares basadas en los nombres de tus columnas y obtuve algunos resultados.

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(); 
    } 
} 

Hope this helps!

+0

Intenté devolver IEnumerable anteriormente pero recibí un error de conversión como se esperaba. Sin embargo, no había pensado en devolver un IEnuerable AsQueryable. –

+0

un posible problema con este enfoque es que no está haciendo una unión pura, por lo tanto, si necesita agregar otra combinación fuera del contexto del préstamo, no podrá por lo que puedo ver. –

+0

Bueno, funcionó. Podemos eliminar la cláusula where en la combinación Método y en lugar de hacer una selección del Método, simplemente realice una unión pura.El truco aquí es que el método tiene que devolver un IEnumerable . Assueryable Esto nos permite hacer combinaciones de contexto cruzadas, y hasta ahora no veo ningún golpe de rendimiento. –

0

Favorezco la creación de un contexto de datos separado que contai Son solo las dos tablas a las que te quieres unir. Pero supongo que podría mantener una tabla temporal (que contenga datos del primer contexto) en el segundo contexto, y luego unirse a la tabla temporal.

+0

creando un contexto de datos separado donde solo se necesitan las dos tablas es una posibilidad, sin embargo, esto no es una necesidad aislada, es solo un ejemplo de una necesidad de esta solución. Quiero evitar crear un contexto de datos aislado cada vez que necesito satisfacer esta necesidad. –

3

Este es el "trabajo en torno a" que hemos encontrado ...

Construimos nuestras mesas desde la otra base de datos de forma manual y si es en el mismo servidor, entonces el prefijo del nombre de la tabla con:

<DatabaseName>.<SchemaName>.<YourTableName> 

si están en un servidor vinculado entonces usted tiene que prefijar con el nombre del servidor, así:

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

Esto le permitirá hacer une y devolver una que no ejecutados aún Queryable ... que es lo que queríamos. Las otras 2 maneras de involucrar la unión de IEnumerables en memoria, lo que significa que extrae todos los registros antes de hacer la unión (arriba) y hacer una unión IQueryable usando un método contains que tiene limitaciones ...

Espero que en el futuro DataContext se construirá lo suficientemente inteligente como para saber que si los servidores están vinculados, entonces puede hacer combinaciones entre dos diferentes.

+0

Si bien es una buena idea, en este caso no es una opción. Gracias por la sugerencia, sin embargo. –