c# - linqpad 5 full
¿Cómo funciona la sintaxis de la expresión LINQ con Include() para cargar con entusiasmo? (5)
Al hacer la consulta básica mencionada en su pregunta publicada, no podrá ver las propiedades del usuario a menos que devuelva un tipo anónimo de la siguiente manera:
from a in Actions
join u in Users on a.UserId equals u.UserId
select new
{
actionUserId = a.UserId
.
.
.
userProperty1 = u.UserId
};
Sin embargo, para usar el método Include en ObjectContext, puede usar lo siguiente:
Asegúrese de tener desactivado LazyLoading utilizando la siguiente línea:
entities.ContextOptions.LazyLoadingEnabled = false;
Luego proceder por
var bar = entities.Actions.Include("User");
var foo = (from a in bar
select a);
Tengo una consulta a continuación, pero quiero realizar una Include () para cargar las propiedades. Acciones tiene una propiedad de navegación, Usuario (Action.User)
1) Mi consulta básica:
from a in Actions
join u in Users on a.UserId equals u.UserId
select a
2) Primer intento:
from a in Actions.Include("User")
join u in Users on a.UserId equals u.UserId
select a
Pero Action.User no está poblado.
3) Intente cargar con entusiasmo ''Usuario'' en la propiedad de navegación en acción fuera de la consulta:
(from a in Actions
join u in Users on a.UserId equals u.UserId
select a).Include("User")
En LINQPad probando Include''s recibo un error:
''System.Linq.IQueryable'' no contiene una definición para ''Include'' y no hay un método de extensión ''Include'' que acepte un primer argumento del tipo ''System.Linq.IQueryable'' (puede presionar F4 para agregar una directiva de uso o una referencia de ensamblaje )
Creo que esto se debe a que LINQ no admite Include ().
Así que lo intenté en VS; La consulta 2 se ejecuta, pero devuelve la propiedad del usuario despoblada. Consulta 3: el método de extensión no parece existir, aunque sí existe en la Acción en sí sin la consulta.
Lo descubrí, gracias por las sugerencias de todos modos. La solución es hacer esto (segundo intento en mi pregunta):
var qry = (from a in Actions
join u in Users on a.UserId equals u.UserId
select a).Include("User")
La razón por la que intellisense no mostró Incluir después de la consulta fue porque necesitaba el siguiente uso:
using System.Data.Entity;
Todo funcionó bien haciendo esto.
Mejor, código refactor amigable (EF6)
using System.Data.Entity;
[...]
var x = (from cart in context.ShoppingCarts
where table.id == 123
select cart).Include(t => t.CartItems);
o
var x = from cart in context.ShoppingCarts.Include(nameof(ShoppingCart.CartItems))
where table.id == 123
select cart;
Actualización 3/31/2017
También puede utilizar la sintaxis de lambda en ambos métodos:
var x = from cart in context.ShoppingCarts.Include(p => p.ShoppingCart.CartItems))
where table.id == 123
select cart;
Si lo que desea es una consulta que devolverá todas las entidades de Action
cuya entidad de User
asociada exista realmente a través de la propiedad clave externa Action.UserId
, esto lo hará:
var results = context.Actions
.Include("User")
.Where(action =>
context.Users.Any(user =>
user.UserId == action.UserId));
Sin embargo , no tiene que usar propiedades de clave externa para realizar el filtrado , ya que también tiene propiedades de navegación . Por lo tanto, su consulta se puede simplificar filtrando la propiedad de navegación Action.User
lugar, como en este ejemplo:
var results = context.Actions
.Include("User")
.Where(action => action.User != null);
Si su modelo indica que la propiedad Action.User
nunca puede ser nula (es decir, la clave foránea Action.UserId
no es anulable en la base de datos) y lo que desea son realmente todas las entidades de Action
con sus Users
asociados, entonces la consulta se vuelve aún más sencilla.
var results = context.Actions.Include("User");
Yo uso para esto la opción LoadWith
var dataOptions = new System.Data.Linq.DataLoadOptions();
dataOptions.LoadWith<Action>(ac => as.User);
ctx.LoadOptions = dataOptions;
Eso es. ctx es su DataContext. Esto funciona para mí :-)