Consulta EntityFramework compleja con varias tablas y relación de muchos a muchos

Me está costando muchísimo conseguir que Entity Framework haga lo que quiero. Estoy escribiendo un agregador de feeds para poder agregar varios feeds rss a una "FeedList" que agrupará todos los podcasts individuales y los ordenará por pubDate.

Clases (todas excepto FeedListFeed tienen una columna de identidad llamada Id):

  1. Feed (Id es la clave principal de identidad, tiene la propiedad List Items)
  2. FeedItem (Id es la clave principal de identidad, como las propiedades int FeedId y Feed Feed)
  3. FeedList (FeedListName es una cadena y la propiedad List Feeds)
  4. FeedListFeed (tabla de vinculación de varios a varios, propiedades FeedListId y FeedId)

Estas asignaciones parecen funcionar:

modelBuilder.Entity<FeedListFeed>().HasKey(x => x.FeedId).HasKey(x => x.FeedListId);
modelBuilder.Entity<FeedList>()
.HasMany(fl => fl.Feeds).WithMany(f => f.FeedLists)
.Map(t => t.MapLeftKey("FeedListId")
.MapRightKey("FeedId")
.ToTable("FeedListFeeds"));

Ahora lo que quiero hacer es obtener las últimas 20 entradas FeedListItem para Feeds en una FeedList dado el FeedListName. Se me ocurrió esto, pero ¿hay una mejor manera de hacerlo? ¿La consulta expandirá realmente todos los elementos o será lo suficientemente inteligente como para hacerlo en el lado de SQL?

var query =
    from fl in ctx.FeedLists.Include("Feeds").Include("FeedItems")
    from f in fl.Feeds
    from fi in f.Items
    where fl.FeedListName == id
    orderby fi.PubDate descending
    select fi;
List<FeedItem> items = query.Take(20).ToList();

Si intento vincular las tablas manualmente usando las columnas Id, aparece el error Invalid object name 'dbo.FeedListFeeds1'. Si sacara las Listas que vinculan las tablas entre sí, ¿ayudaría esto? ¿Hay algún otro mapeo que permita que esto funcione?

var query =
    from fl in ctx.FeedLists
    join flf in ctx.FeedListFeeds on fl.Id equals flf.FeedListId
    join fi in ctx.FeedItems on flf.FeedId equals fi.FeedId
    where fl.FeedListName == id
    orderby fi.PubDate descending
    select fi;

preguntado el 16 de mayo de 11 a las 18:05

1 Respuestas

Elimina esta línea de tu mapeo ...

modelBuilder.Entity<FeedListFeed>()
            .HasKey(x => x.FeedId)
            .HasKey(x => x.FeedListId);

... porque tiene 2 problemas:

1) Si desea una clave compuesta, no debe encadenar HasKey pero cree la clave a través de un tipo anónimo:

modelBuilder.Entity<FeedListFeed>()
            .HasKey(x => new { x.FeedId, x.FeedListId });

2) (más importante) Esta línea permite que EF considere FeedListFeed como una entidad que no está en su modelo. El resultado es que EF crea una tabla separada para él con el nombre FeedListFeeds1 porque FeedListFeeds está reservado como nombre de tabla en su mapeo de muchos a muchos (.ToTable("FeedListFeeds")). Para el mapeo de muchos a muchos, no es necesario crear una clase para la tabla de enlace. EF administra la tabla de vinculación internamente.

Editar

A continuación, también puede quitar el FeedListFeed clase completamente por supuesto.

Para la consulta, probaría entonces:

var query = from fi in ctx.FeedItems
            where fi.Feed.FeedLists.Any(fl => fl.FeedListName == id)
            orderby fi.PubDate descending
            select fi;

Creo que tiene todas las propiedades de navegación necesarias en sus clases de modelo para que esta consulta sea posible.

contestado el 17 de mayo de 11 a las 00:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.