I'm working with EF6. I have a module with multiple ICollections. My solution to retrieve the lists of objects is similar but I find it dumb, as I need to rewrite this on all the pages where I need IEnumerable<BookModel> GetAllBook.
IEnumerable<BookModel> GetAllBook = DBContext.BookModels.Include(x => x.AssociatedNames).Include(e => e.BlogModel);
I read several topics on this but these stood out. From what I understood, the answer is written in the DbContext.cs with the DbSets. But does the BookModule have a complete list of example authors? Without the need of including another time?
Include several references
I also read
Why does EF Core One-to-Many relationship collection return null?
public class BookModel
{
[Key]
public int BookModelID{ get; set; }
public virtual ICollection<AssociatedNames>? AssociatedNames { get; set; }
public virtual List<BookModel>? relatedSeries { get; set; }
public virtual List<BookModel>? RecommendedBookModels { get; set; }
public virtual ICollection<AuthorModel>? Authormodels { get; set; }
public virtual ICollection<ArtistModel>? ArtistModels { get; set; }
public virtual ICollection<VoiceActorModel>? VoiceActors { get; set; }
public virtual ICollection<GenresModel>? GenresModels { get; set; }
public virtual ICollection<TagModel>? TagsModels { get; set; }
}
My question is there a way for my bookModel have the complete lists of objects without needing to use Include again, and again.
Best regards
What you need in this cas is the AutoInclude feature introduced with EF6 , so You will have to go into the OnModelCreating Method and add the following lines ( you update that to your use case , depends on which related entities you want to be autoIncluded ):
modelBuilder.Entity<BookModel>().Navigation(e => e.Authormodels).AutoInclude();
modelBuilder.Entity<BookModel>().Navigation(e => e.Artistmodels).AutoInclude();
and if , for a specific cas you need only the books , and you want to get rid of the autoIncludes , then us can use the IgnoreAutoIncludes feature like below :
var books = context.BookModels.IgnoreAutoIncludes().ToList();
Fore more details about this you can look up this documentation or this video
Related
I'm trying to load an object (a) and that object has a collection of objects (b), each object:b has single objects attached to them.
I've cut down the code below to show you how it's setup.
I can without any problems load 'MyImprovement'.
I can in that same moment load the collection of 'MyCondition'.
But what I fail to load is 'MyComponent' that is referenced in the 'MyCondition'...
I managed to find some samples using .Include and .ThenInclude, however, .ThenInclude does not exist from what I can see?
I've tried every possible aspect of this and I still think that it should be possible to do,... right?
Anyone who's up for the task? I'm completely lost right now, so please help!
Thanks in advance!
/Karl
public class MyImprovement
{
[Key]
public int MyImprovementId { get; set; }
public virtual ICollection<MyCondition> Conditions { get; set; }
}
public class MyCondition
{
[Key]
public int MyConditionId { get; set; }
public int? ComponentId { get; set; }
public virtual MyComponent ConditionalMyComponent { get; set; }
}
public class MyComponent
{
[Key]
public int ComponentId { get; set; }
public string PDNumber { get; set; }
}
// Code to load the first 2 levels of objects
MyImprovement improvement = dbx.MyImprovements
.Include("Conditions")
.Where(x => x.ImprovementId == id)
.First();
If you want to eager-load complex entity graph, you can combine multiple .Include()- Methods with following style:
MyImprovement improvement = dbx.MyImprovements
.Include("Conditions")
.Include("Conditions.ConditionalMyComponent")
.Where(x => x.ImprovementId == id)
.First();
So I have a class with a static method that uses EF to retrieve certain set of mailing lists and maps to the class.
public static List<MailingList> GetMailingListsForUser(IUsersAccess user, IProspectorDataSource db )
{
return db.MailingLists.Where(x => x.UserID == user.UserID).ToList()
.Select(y => new MailingList(y, db) ).ToList();
}
Now though I have a proc that will return the MailingList plus some extra stuff. I don't want to add these extra columns (which will be used in other sections and areas of functionality) to this class. What is the best way to address this?
I am thinking a Factory Pattern that will generate a different class that implements different contracts (interfaces) based on whats needed. Going to try implement it and will post code/working when completed.
Was wondering what other people have done in instances like this and if there are any better ways to address this.
Edit: (some extra information to help people understand what I mean).
public class MailingList
{
public int MailingListID { get; set; }
public string Name { get; set; }
public string Comments { get; set; }
public List<string> Tags { get; set; }
public int UserID { get; set; }
public System.DateTime DateCreated { get; set; }
public string CreatedBy { get; set; }
public System.DateTime LastModified { get; set; }
public string ModifiedBy { get; set; }
public List<MailingListAddress> MailingListAddresses { get; set; }
That is the definition of an object that we return. Now there is a new instance where I am going to return some extra columns from a proc and map to MailingList. So I could just add the properties to here but the issue is MailingListAddresses will be null as they will not be returned by the stored proc. So is there a way to map to specific properties and not have to return null for MailingListAddresses to the front end every time.
This was fixed by a senior developer who ended up going with the factory pattern. I will add the code when I get back to work :)
How can I specify with data annotation or fluentapi, a list of string in my model like a list of foreign keys? I know that I could specify the User model in the list, but I'd like to have a list of strings.
Model Example:
public class Allocation
{
[Key]
public int Id { get; set; }
...
public List<string> Users { get; set; }
}
public class User
{
[Key]
public string Id { get; set; }
...
}
Even expert developers FAIL MISERABLY when it comes to Entity Framework, so I'll let you into a little secret. Write the code you wish you had.
With regards directly to your scenario, you're over complicating things unnecessarily. Let Entity Framework do it's job and handle the relationships for you!
All you should need to model this relationship is...
public class Allocation
{
public int Id { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public virtual Allocation Allocation { get; set; }
}
Now please note that I DID NOT write the code I wish I had, but that's because the code I wish I had was overkill for this question, and very high-level. If you do however want to delve into this subject and find out what Entity Framework really can do for you, I would start here...
https://lostechies.com/jimmybogard/2010/02/04/strengthening-your-domain-a-primer/
I have the entities:
public class Plugin
{
public virtual int Id { get; set; }
public virtual int Version { get; set; }
public virtual Plugin ParentPlugin { get; set; }
public virtual IEnumerable<Setting> Settings { get; set; }
}
public class Setting
{
public virtual int Id { get; set; }
public virtual Plugin Plugin { get; set; }
public virtual int Version { get; set; }
}
The problems is that when I added ParentPlugin, it added a ParentPlugin_Id to the Setting table in the DB. I can't figure out why it did this, however I'd like for Setting to only have a Plugin_Id not both Plugin_Id and ParentPlugin_Id in the database.
So, I would like to know 2 things to receive bounty:
1. How can I remove the ParentPlugin_Id reference from Setting?
2. And why did it do this in the first place (link to doc is ok, I could not find one explaining this)?
I'm using Fluent Nhibernate's automapping, mostly all defaults.
By specifying the exact FK name I was able to remove the extra ParentPlugin_Id. A bit counter intuitive to have to add an FK instead of removing one but...
.Override<Plugin>(m => m.HasMany(c => c.Settings).KeyColumn("Plugin_Id"))
This was figured out by a deeper understanding of the Foreign Key Conventions (https://github.com/jagregory/fluent-nhibernate/wiki/Auto-mapping)
I just declared some code-first models for a new project that uses EntityFramework.
public class BlogEntry
{
public long Id { get; set; }
public long AuthorId { get; set; }
public DateTime PublishedStamp { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public virtual User Author { get; set; }
}
public class User
{
public long Id { get; set; }
public string Email { get; set; }
// ...
}
class BlogDb : DbContext
{
public DbSet<BlogEntry> Entries { get; set; }
public DbSet<User> Users { get; set; }
}
Now suppose I want to retrieve the 10 most recent blog entries:
var entries = new BlogDb().Entries.OrderByDescending(...).Take(10).ToList();
The problem now is that accessing entry.Author will cause another database query. You wouldn’t want a separate such query for every blog entry. Now, it is my understanding that the purpose of Include is exactly this case, so I can say:
var entries = new BlogDb().Entries.Include(e => e.Author).(...).ToList();
However, that method doesn’t seem to exist. There is only an Include(string), like this:
var entries = new BlogDb().Entries.Include("Author").(...).ToList();
but this is annoying because it’s not compile-time checked and will be missed by the rename refactoring. Surely the version with the lambda is the “correct” approach.
Where did that method go? Is it no longer included in EntityFramework?
(I know that I can write an extension method for myself to achieve this, so you don’t have to. I’d just like to know whether I’m missing something.)
using System.Data.Entity;
It's in EF v4.1 and above, but you need a reference as it is an extension method.
Edit (thanks to #EastonJamesHarvey)
If using EF Core the import should be:
using Microsoft.EntityFrameworkCore;