开发者

Complex EntityFramework query with multiple tables and many to many relationship

开发者 https://www.devze.com 2023-03-06 19:18 出处:网络
I\'m having a heck of a time getting Entity Framework to do what I want.I\'m writing a feed aggregator so I can add multiple rss feeds to a \"FeedList\" that will group all the individual podcasts and

I'm having a heck of a time getting Entity Framework to do what I want. I'm writing a feed aggregator so I can add multiple rss feeds to a "FeedList" that will group all the individual podcasts and order by pubDate.

Classes (all but FeedListFeed have identity column called Id):

  1. Feed (Id is identity primary key, has List Items property)
  2. FeedItem (Id is identity primary key, as int FeedId and Feed Feed properties)
  3. FeedList (FeedListName is string and List Feeds property)
  4. FeedListFeed (many-to-many linking table, FeedListId and FeedId properties)

These mappings seems to work:

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"));

Now what I want to do is get the latest 20 FeedListItem entries for Feeds in a FeedList given the FeedListName. I've come up with this, but is there a better way to do it? Will the query actually expand all the items, or will it be smart enough to do it on the SQL side?

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

If I try to link the tables manually using the Id columns, I get the error Invalid object name 'dbo.FeedListFeeds1'. If I took out the Lists that link the tables to each other would this help? Is there some other mapping that let this work?

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.FeedListNam开发者_运维百科e == id
    orderby fi.PubDate descending
    select fi;


Remove this line from your mapping ...

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

... because it has 2 issues:

1) If you want a composite key you must not chain HasKey but create the key via an anonymous type:

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

2) (more important) This line lets EF consider FeedListFeed as an entity which it isn't in your model. The result is that EF creates a separate table for it with the name FeedListFeeds1 because FeedListFeeds is reserved as table name in your many-to-many mapping (.ToTable("FeedListFeeds")). For many-to-many mapping you don't need to create a class for the linking table. The linking table is managed by EF internally.

Edit

You can then also remove the FeedListFeed class completely of course.

For the query I would try then:

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

I think you have all the necessary navigation properties in your model classes so that this query should be possible.

0

精彩评论

暂无评论...
验证码 换一张
取 消