Navigation property is null when using Include - EF [on hold] - c#

I'm calling
Persons.Include(e => e.City)
in "Get()" method in my web API.
The navigation property "ICollection persons" in "City" model return null.
So when I use "PostMan" to get values it throw error
Could not get any response
There was an error connecting to http://localhost:13236/api/values.
I linked a test project on GitHub :
https://github.com/MajdAlbaho/SampleWebAPI

To enable lazy loading ICollection property must be marked as virtual.
so in your example, instead of:
public ICollection<Person> Persons { get; set; }
define it like this:
public virtual ICollection<Person> Persons { get; set; }
This article may be helpful: Entity Framework Loading Related Entities

Related

SQLite Exception when creating table using OData object containing reference to itself

The following code:
oc.CreateTablesAsync(typeof(ODataService.UserInformationListItem), typeof(ODataService.CategoriesItem), typeof(ODataService.PostsItem));
Gives me this exception:
System.NotSupportedException: Don't know about ODataApp.ODataService.UserInformationListItem
At first I was just creating a table for PostsItems, which is the object i need to store, but then I got the above exception but then for ODataApp.ODataService.CategoriesItem.
Since PostItem has the property Category, which is a List<CategoriesItem> I figured I had to add CategoriesItem as a table as well.
After doing so I got an error for the property CreatedBy on PostsItems, which is a UserInformationListItem, now this is when it gets tricky.
I also added UserInformationListItem to the CreateTables function which gave me my current problem.
The object UserInformationListItem also contains a CreatedBy property which is also an UserInformationListItem.
I'm looking for a way around this without having to alter or recreate local versions of these objects.
These objects are defined on Sharepoint which I cannot edit, and are obtained by the OData service reference. If anymore information is needed to supply me with an answer, please let me know
Based on your sample code I presume you're using sqlite-net.
Sqlite-net is not a real ORM - it only has support for basic data types and can't handle your custom types as properties. You can check it your self in SqlType() static method of Orm class (SQLite.cs).
It's not self referencing that's causing problems, it's any references between the classes. Creating tables for the following two classes will fail as well with NotSupportedException:
public class CategoryItem
{
public int Id { get; set; }
public string Title { get; set; }
}
public class PostItem
{
public int Id { get; set; }
public string Label { get; set; }
public List<CategoryItem> Categories { get; set; }
}
You'll need to create your own "database" classes which will map to database tables one-to-one. To handle UserInformationListItem you'll just add it's key value as a property to PostItem. If PostItem and CategoryItem have a many to many relationship you'll need to add a cross-reference table as well.

Entity Framework Core 2 Navigation Properties only load up when accessed [duplicate]

As I remember in EF navigation property should be virtual:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Tags { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
But I look at EF Core and don't see it as virtual:
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
}
Is it not required anymore?
virtual was never required in EF. It was needed only if you want lazy loading support.
Since Lazy loading is not yet supported by EF Core, currently virtual have no special meaning. It would when (and if) they add lazy loading support (there is a plan for doing so).
It has never been required...
Thanks to other's answer here, i see that EF core does not even support the Lazy loading... It makes the virtual key word pretty... useless in CORE
BUT NORMALLY :
1. if you declare your property virtual :
Your virtual property (by default) won't be loaded right away when querying the main object. It will be retreive from the database ONLY if you try to access it, or access one of it's components.
And this is called lazy loading.
2. if you declare it non-virtual :
Your property will (by default) be loaded right away along with all the other property in your main entity. This means your property will be ready to access : it has already been retreived. Entity won't have to query again the database because you access this property.
This is called eagerly loading.
My opinion :
More often i choose eagerly loading (non-virtual) because most of the time, i need every property of every entity to be used along without having to query back (faster in the case you really want everything quick) but if you access this property only once in a while (your not listing anything) and you want more often just the rest of the informations exept THIS one, then make it virtual so this property won't slow down the rest of the query just for a few access.
Hope this was clear...
Exemples :
Where i would NOT use virtual (Eagerly) :
foreach(var line in query)
{
var v = line.NotVirtual; // I access the property for every line
}
Where i would use virtual or lazy loading :
foreach(var line in query)
{
if(line.ID == 509) // because of this condition
var v = line.Virtual; // I access the property only once in a while
}
one last thing :
If you don't query over 1 000 lines of a database, then whatever you choose won't have a big effect. Also, you can declare these property virtual and if you want to test the other way around, you just have to do this :
context.LazyLoadingEnabled = false;
It will cancel the virtual effect.
Edit
For newer versions of EF :
WhateverEntities db = new WhateverEntities()
db.Configuration.LazyLoadingEnabled = false;
In EF Core has choosen the path of discouraging lazy loading by default.
Also i think this feature is still not implemented following this issue.
https://github.com/aspnet/EntityFramework/issues/3312
With the previous versions of EF the virtual navigation properties allowed to lazy load the related entities.
I guess loading navigation properties for now can be achived only with .Include(...)
EDIT:
There are several ways of loading related entities which are supported in Core.
If you are interested: https://docs.microsoft.com/en-us/ef/core/querying/related-data
Things have changed since the accepted answer was written. In 2018, Lazy Loading is now supported as of Entity Framework Core 2.1 for two different approaches.
The simpler way of the two is using proxies, and this will require the properties desired to be lazily loaded to be defined with virtual. To quote from the linked page:
The simplest way to use lazy-loading is by installing the Microsoft.EntityFrameworkCore.Proxies package and enabling it with a call to UseLazyLoadingProxies. [...] EF Core will then enable lazy-loading for any navigation property that can be overridden--that is, it must be virtual and on a class that can be inherited from.
And here is the provided sample code:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public virtual Blog Blog { get; set; }
}
There is another way of doing Lazy Loading without proxies, which is to inject ILazyLoader into the constructor of the data type. This is explained in here.
In short, there are two ways to perform Lazy Loading: with and without proxies. virtual is required if and only if you wish to support Lazy Loading with proxies. Otherwise, it is not.
Update: an initial implementation of lazy loading, planned for EF Core 2.1, will require navigation properties to be declared virtual. See https://github.com/aspnet/EntityFrameworkCore/issues/10787, and more generally to track progress on lazy loading, see https://github.com/aspnet/EntityFrameworkCore/issues/10509.

EF and Initializing Navigation Property

I am a bit of confusion. I have following Entity Class for EF.
public class Identity
{
public Identity()
{
}
[Key]
public long Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public virtual ClientDetails ClientDetails { get; set; }
}
I read in couple of places in StackOverFlow that it is not recommended to initialize navigation property (not collection) in the constructor.
Could someone help me understand why is this so ?
Thanks
Anu
Navigation properties are populated by entity framework (at least when you use the Include() method to tell it to populate that object) when you retrieve an item. Under the cover, it will create a foreign key to the object you are navigating to. This can be seen inside of the generated migrations.
Any code in your constructor is effectively going to be ignored when entity framework retrieves the items from the database, as it will use reflection to instantiate the instance of the class (this process requires the default constructor, or it will throw a runtime exception), and then use reflection to set the values for the various properties using what it has retrieved from the database.

navigation property should be virtual - not required in ef core?

As I remember in EF navigation property should be virtual:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Tags { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
But I look at EF Core and don't see it as virtual:
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
}
Is it not required anymore?
virtual was never required in EF. It was needed only if you want lazy loading support.
Since Lazy loading is not yet supported by EF Core, currently virtual have no special meaning. It would when (and if) they add lazy loading support (there is a plan for doing so).
It has never been required...
Thanks to other's answer here, i see that EF core does not even support the Lazy loading... It makes the virtual key word pretty... useless in CORE
BUT NORMALLY :
1. if you declare your property virtual :
Your virtual property (by default) won't be loaded right away when querying the main object. It will be retreive from the database ONLY if you try to access it, or access one of it's components.
And this is called lazy loading.
2. if you declare it non-virtual :
Your property will (by default) be loaded right away along with all the other property in your main entity. This means your property will be ready to access : it has already been retreived. Entity won't have to query again the database because you access this property.
This is called eagerly loading.
My opinion :
More often i choose eagerly loading (non-virtual) because most of the time, i need every property of every entity to be used along without having to query back (faster in the case you really want everything quick) but if you access this property only once in a while (your not listing anything) and you want more often just the rest of the informations exept THIS one, then make it virtual so this property won't slow down the rest of the query just for a few access.
Hope this was clear...
Exemples :
Where i would NOT use virtual (Eagerly) :
foreach(var line in query)
{
var v = line.NotVirtual; // I access the property for every line
}
Where i would use virtual or lazy loading :
foreach(var line in query)
{
if(line.ID == 509) // because of this condition
var v = line.Virtual; // I access the property only once in a while
}
one last thing :
If you don't query over 1 000 lines of a database, then whatever you choose won't have a big effect. Also, you can declare these property virtual and if you want to test the other way around, you just have to do this :
context.LazyLoadingEnabled = false;
It will cancel the virtual effect.
Edit
For newer versions of EF :
WhateverEntities db = new WhateverEntities()
db.Configuration.LazyLoadingEnabled = false;
In EF Core has choosen the path of discouraging lazy loading by default.
Also i think this feature is still not implemented following this issue.
https://github.com/aspnet/EntityFramework/issues/3312
With the previous versions of EF the virtual navigation properties allowed to lazy load the related entities.
I guess loading navigation properties for now can be achived only with .Include(...)
EDIT:
There are several ways of loading related entities which are supported in Core.
If you are interested: https://docs.microsoft.com/en-us/ef/core/querying/related-data
Things have changed since the accepted answer was written. In 2018, Lazy Loading is now supported as of Entity Framework Core 2.1 for two different approaches.
The simpler way of the two is using proxies, and this will require the properties desired to be lazily loaded to be defined with virtual. To quote from the linked page:
The simplest way to use lazy-loading is by installing the Microsoft.EntityFrameworkCore.Proxies package and enabling it with a call to UseLazyLoadingProxies. [...] EF Core will then enable lazy-loading for any navigation property that can be overridden--that is, it must be virtual and on a class that can be inherited from.
And here is the provided sample code:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public virtual Blog Blog { get; set; }
}
There is another way of doing Lazy Loading without proxies, which is to inject ILazyLoader into the constructor of the data type. This is explained in here.
In short, there are two ways to perform Lazy Loading: with and without proxies. virtual is required if and only if you wish to support Lazy Loading with proxies. Otherwise, it is not.
Update: an initial implementation of lazy loading, planned for EF Core 2.1, will require navigation properties to be declared virtual. See https://github.com/aspnet/EntityFrameworkCore/issues/10787, and more generally to track progress on lazy loading, see https://github.com/aspnet/EntityFrameworkCore/issues/10509.

Entity framework 'include' including more than it should

I have a class Program:
[Table("Program")]
public class Program
{
[Key]
public long ProgramId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Activity> Activities { get; set; }
public virtual ICollection<User> Users { get; set; }
public virtual ICollection<TimeEntry> TimeEntries { get; set; }
}
The typical usage pattern is to grab a Program and all it's associated Activities. Much less often need Programs and their related Users or TimeEntries.
So, to return json of all the programs and their related activities. I used .Include:
//...
var programActivities = db.Programs.Include(p => p.Activities);
As expected the json emitted has programs and nested activities. Good.
But, it also returned each Program's associated TimeEntries and Users. Didn't expect that! Other articles i've read indicate that you use one .Include for each of the related objects to be returned, so it would follow that if you don't use an .include for an object, you don't get it.
Is there an additional switch or option i have to use to exclude the other related objects?
Don't declare your navigation properties as virtual or disable Lazy Loading behavior. Lazy loading is enable by default and is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook. So, if you want to work with JSON I recommend you turn off lazy loading:
public class YourContext : DbContext
{
public YourContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Now you can load the related entities you want using the Include extension method as part of a query. This behavior is called Eager Loading.
These links can help you to understand better what I explain in my answer:
Loading Related Entities (read the lazy loading section)
Requirements for Creating POCO Proxies
In Entity Framework, when using the Include statement like so db.Programs.Include(p => p.Activities), you are basically ensuring that the navigation property will be eagerly loaded, rather than lazy loaded. Essentially, this means using one database query to get the data for a Program and its related Activites rather than two.
The problem is, what if lazy loading is enabled for the context, any attempt to get the rest of the navigation properties will result in extra database calls. This is probably what's happening when the JSON serializer tries to serialize your Program objects.
In order to prevent this, you should probably look for a way to exclude the navigation properties from being serialized and so they will never be loaded from the database. For example:
[JsonIgnore]
public virtual ICollection<User> Users { get; set; }
[JsonIgnore]
public virtual ICollection<TimeEntry> TimeEntries { get; set; }
This will allow you to keep lazy loading on, while preventing the loading of the rest of the properties. It all depends on your application design, for example if you need to use lazy loading or if your navigation properties need to be exposed occasionally.

Resources