2011-05-25 8 views
7

En un proyecto actualmente estoy trabajando en, necesito acceder a 2 bases de datos en LINQ de la siguiente manera:Evitar el límite de 2.100 parámetro en LINQ to SQL

  1. puedo obtener una lista de todos los números de viaje entre un rango de fechas especificado desde DB1, y almacenar esto como una lista de valores 'largos'

  2. Realizo una consulta extensa con muchas combinaciones en DB2, pero solo mirando los viajes que tienen su número de viaje incluido en el anterior lista.

El problema es que la lista de viaje del DB1 vuelve a menudo más de 2100 artículos - y, por supuesto, golpeó el límite de 2.100 parámetro en SQL, lo que hace que mi segunda consulta falle. He estado buscando formas de evitar esto, como se describe en here, pero esto tiene el efecto de cambiar esencialmente mi consulta a LINQ-to-Objects, lo que causa muchos problemas con mis uniones

¿Hay alguna otra solución? ¿Puedo hacer?

+4

¿No puede devolver un conjunto de resultados en lugar de 2100 parámetros? –

+0

¿Ha considerado lotear la operación de inserción? –

+0

Hay una solución que usa un único parámetro XML en [este problema de conexión] (https://connect.microsoft.com/VisualStudio/feedback/details/475984/use-an-xml-type-parameter-in-order-to- exceda-el-2100-parameter-limit-in-linq-to-sql-when-filtering-via-a-local-collection).Pero estoy de acuerdo con Guillame: debería coordinar esto entre las dos bases de datos si puede. – Rup

Respuesta

5

como LINQ a SQL puede llamar a procedimientos almacenados, puede

  • tener un procedimiento almacenado que toma una matriz como entrada a continuación, coloca los valores en una tabla temporal para unirse en
  • asimismo por tomando una cadena que divide el proceso almacenado

O cargue todos los valores en una tabla temporal usted mismo y únase a esa tabla.

Sin embargo tal vez debería replantearse el problema:

  • servidor SQL puede ser configurado para permitir consulta en tablas en otras bases de datos como Oracle(), si se permite que esto puede ser una opción para usted.
  • ¿Podría utilizar algún sistema de replicación para mantener actualizada una tabla de números de viaje en DB2?
+0

Gracias, la idea de tabla temporal es fantástica y funciona perfectamente. La única preocupación que tengo es tener usuarios concurrentes que usan el sistema a la vez puede causar problemas, aunque tengo una idea de almacenar el nombre de usuario con el número de viaje en la tabla temporal – Chris

+0

@chris, "Las tablas temporales locales son visibles solo en el actual sesión ", ya que hay una sesión diferente para cada conexión Ado.Net, debería estar bien con una" Tabla temporal local ". –

1

Puede dividir su consulta o utilizar una tabla temporal en la base de datos2 llena de resultados de la base de datos1.

2

No estoy seguro de si esto ayudará, pero tuve un problema similar para una consulta única que estaba escribiendo en LinqPad y terminé definiendo y usando una tabla temporal como esta.

[Table(Name="#TmpTable1")] 
public class TmpRecord 
{ 
    [Column(DbType="Int", IsPrimaryKey=true, UpdateCheck=UpdateCheck.Never)] 
    public int? Value { get; set; }   
} 

public Table<TmpRecord> TmpRecords 
{ 
    get { return base.GetTable<TmpRecord>(); } 
} 

public void DropTable<T>() 
{ 
    ExecuteCommand("DROP TABLE " + Mapping.GetTable(typeof(T)).TableName ); 
} 

public void CreateTable<T>() 
{ 
    ExecuteCommand(
    typeof(DataContext) 
    .Assembly 
    .GetType("System.Data.Linq.SqlClient.SqlBuilder") 
    .InvokeMember("GetCreateTableCommand", 
     BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod 
    , null, null, new[] { Mapping.GetTable(typeof(T)) }) as string 
    );  
} 

uso es algo así como

void Main() 
{ 
    List<int> ids = .... 

    this.Connection.Open(); 
    // Note, if the connection is not opened here, the temporary table 
    // will be created but then dropped immediately. 

    CreateTable<TmpRecord>();  
    foreach(var id in ids) 
     TmpRecords.InsertOnSubmit(new TmpRecord() { Value = id}) ; 
    SubmitChanges(); 

    var list1 = (from r in CustomerTransaction 
     join tt in TmpRecords on r.CustomerID equals tt.Value 
     where .... 
     select r).ToList(); 

    DropTable<TmpRecord>();  
    this.Connection.Close();  

}

En mi caso, la tabla temporal sólo tenía una columna int, pero debe ser capaz de definir lo que sea la columna (s) tipo usted quiere , (siempre que tenga una clave principal).