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):
- Feed (Id is identity primary key, has List Items property)
- FeedItem (Id is identity primary key, as int FeedId and Feed Feed properties)
- FeedList (FeedListName is string and List Feeds property)
- 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.
精彩评论