2011-11-23 17 views
10

Estoy intentando forzar a Linq a realizar una unión interna entre dos tablas. Daré un ejemplo.Obligar a linq a realizar uniones internas

CREATE TABLE [dbo].[People] (
    [PersonId] [int] NOT NULL, 
    [Name] [nvarchar](MAX) NOT NULL, 
    [UpdatedDate] [smalldatetime] NOT NULL 
    ... Other fields ... 
) 

CREATE TABLE [dbo].[CompanyPositions] (
    [CompanyPositionId] [int] NOT NULL, 
    [CompanyId] [int] NOT NULL, 
    [PersonId] [int] NOT NULL, 
    ... Other fields ... 
) 

Ahora estoy trabajando con la base de datos inusual ya que hay una razón más allá de mi control para que la gente no aparecer en la tabla personas, pero tienen un registro en CompanyPositions. Quiero filtrar las posiciones de la compañía con personas desaparecidas al unirme a las tablas.

return (from pos in CompanyPositions 
     join p in People on pos.PersonId equals p.PersonId 
     select pos).ToList(); 

Linq ve esta unión como redundante y la elimina del SQL que genera.

SELECT 
[Extent1].[CompanyPositionId] AS [CompanyPositionId], 
[Extent1].[CompanyId] AS [CompanyId], 
.... 
FROM [dbo].[CompanyPositions] AS [Extent1] 

Sin embargo, no es redundante en mi caso. Puedo arreglarlo así

// The min date check will always be true, here to force linq to perform the inner join 
var minDate = DateTimeExtensions.SqlMinSmallDate; 

return (from pos in CompanyPositions 
     join p in People on pos.PersonId equals p.PersonId 
     where p.UpdatedDate >= minDate 
     select pos).ToList(); 

Sin embargo, esto ahora crea una cláusula where innecesaria en mi SQL. Como más puro me gustaría eliminar esto. ¿Alguna idea o el diseño actual de la base de datos me ata?

+1

¿Qué estás usando? LINQ to SQL? LINQ a las entidades? ¿Algo más? – svick

+1

¿Su modelo tiene propiedades de navegación? Si es así, podría escribir algo como 'where pos.Person! = Null'. – svick

+0

Estoy usando LinqToSql, he intentado 'where pos.Person! = Null' y 'p.PersonId! = 0' y Linq los elimina. En el caso de 'p.PersonId! = 0' lo cambia a 'pos.PersonId! = 0' que me impresiona incluso si no es lo que estoy buscando. – Magpie

Respuesta

2

Desde PERSONID se declara NOT NULL (y supongo que se declara como una FK a la gente), entonces no estoy seguro cómo podría tener una posición de compañía con una persona que no está asignada; y Linq no puede ver cómo puede emitir, por lo que, como ha observado, Linq considera que la unión es redundante.

+1

Eso tiene sentido, la base de datos con la que estoy trabajando es una versión plana de un maestro mucho más grande y complicado. Solo los datos relevantes para un producto se envían a esto y, lamentablemente, debido a tales registros faltantes no hay FK, estos se aplican en el maestro. En este caso, la persona no se ha publicado, por lo que no se envía desde el máster. Lo ideal sería ni tampoco la posición de la compañía, pero esto está fuera de mi control. Parece que el diseño db es el principal problema aquí. – Magpie

0

Si está utilizando LinqToSql, puede utilizar LoadWith similar a esto:

var context = new MyDataContext(); 
var options = new DataLoadOptions(); 
options.LoadWith<People>(x => x.CompanyPositions); 
context.LoadOptions = options; 
0

No sé cómo forzar a linq a utilizar una unión. Pero la siguiente declaración debería darle el resultado requerido.

return (from pos in CompanyPositions 
     where (p in People select p.PersonId).Contains(pos.PersonId) 
     select pos).ToList(); 
0

transformación ClientSide:

(
from pos in CompanyPositions 
join p in People on pos.PersonId equals p.PersonId 
select new {pos, p} 
).ToList().Select(x => x.pos); 

Más de filtración directa:

from pos in CompanyPositions 
where pos.People.Any() 
select pos 
Cuestiones relacionadas