Why EF navigation property return null?

I have two model
1)

public class Indicator
{
    public long ID { get; set; }
    public string Name { get; set; }
    public int MaxPoint { get; set; }
    public string Comment { get; set; }
    public DateTime DateChanged { get; set; }
    public DateTime DateCreated { get; set; }

    public virtual IList<CalculationType> CalculationTypes { get; set; }
    public virtual IList<TestEntity> TestEntitys { get; set; }
    public virtual IndicatorGroup IndicatorGroup { get; set; }
}

2)
public class CalculationType
{
    public long ID { get; set; }
    public string UnitName { get; set; }
    public int Point { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }

    public virtual Indicator Indicator { get; set; }
    public virtual IList<Сalculation> Calculations { get; set; }
}

I executing this code
var indicator = DataContext.Indicators.FirstOrDefault(i => i.ID == indicatorID);
var test = DataContext.CalculationTypes.FirstOrDefault();

first line return null on navigation property CalculationTypes
enter image description here

Second line return empty collection.enter image description here Why?

UPDATE
snapshot database
Why EF navigation property return null?Why EF navigation property return null?
project link https://github.com/wkololo4ever/Stankin

added Calculation

    public class Сalculation
{
    public long ID { get; set; }

    public virtual CalculationType CalculationType { get; set; }
    public virtual ApplicationUser Creator { get; set; }
}

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

1) Is Lazy Loading enabled? If not, you need to explicitly load your navigation properties with the ‘.Include’ syntax.

2) Are you sure EF should be able to detect that relation? Did you use Code First or Database First?

Edit: 3) Are you sure there is data in your database and that the foreign key from Indicator to IndicatorGroup has a value for that specific record? I am saying this because the value “null” is valid if there is simply no data.

P.S. If you do not see a foreign key on Indicator called “IndicatorGroupId”, there might be an “IndicatorId” on the table “IndicatorGroup”, in which case – going from the names you provided – your database is misconfigured and you will need to use fluent syntax or data attributes to instruct EF on how to make the foreign keys.

Method 2

Try this:

DbContext.Configuration.ProxyCreationEnabled = true;    
DbContext.Configuration.LazyLoadingEnabled = true;

If DbContext.Configuration.ProxyCreationEnabled is set to false, DbContext will not load child objects for some parent object unless Include method is called on parent object. Setting DbContext.Configuration.LazyLoadingEnabled to true or false will have no impact on its behaviours.

If DbContext.Configuration.ProxyCreationEnabled is set to true, child objects will be loaded automatically, and DbContext.Configuration.LazyLoadingEnabled value will control when child objects are loaded.

I think this is problem:

Edit: 3) Are you sure there is data in your database and that the
foreign key from Indicator to IndicatorGroup has a value for that
specific record? I am saying this because the value “null” is valid if
there is simply no data.

P.S. If you do not see a foreign key on Indicator called
“IndicatorGroupId”, there might be an “IndicatorId” on the table
“IndicatorGroup”, in which case – going from the names you provided –
your database is misconfigured and you will need to use fluent syntax
or data attributes to instruct EF on how to make the foreign keys.

Try to this and make sure foreign key is corrected.

public class CalculationType
{
    public long ID { get; set; }
    public string UnitName { get; set; }
    public int Point { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }
    [ForeignKey("IndicatorID")]
    public string IndicatorId { get; set; } //this is the foreign key, i saw in your database is: Indicator_ID, avoid this, rename it to IndicatorID or IndicatorId

    public virtual Indicator Indicator { get; set; }
    public virtual IList<Сalculation> Calculations { get; set; }
}

Method 3

Same behavior, but different root cause than selected answer:

Navigation property can also be null if you turned off myContext.Configuration.AutoDetectChangesEnabled

Very obvious, but this got me when I was implementing some performance improvments.

Method 4

Check this out: Navigation Property With Code First . It mentions about why navigation property is null and the solutions of it.

By default, navigation properties are null, they are not loaded by
default. For loading navigation property, we use “include” method of
IQuearable and this type of loading is called Eager loading.

Eager loading: It is a process by which a query for one type of entity
loads the related entities as a part of query and it is achieved by
“include” method of IQueryable.

Method 5

I experienced this issue, where navigation properites were not loaded, even when the Include statement was present.

The problem was caused by string-comparison differences between SQL Server and EF6 using .NET. I was using a VARCHAR(50) field as the primary key in my customers table and also, as a foreign key field in my audit_issues table. What I did not realize was that my keys in the customers table had two additional white space characters on the end; these characters were not present in my audit_issues table.

However, SQL Server will automatically pad whitespace for string comparisons. This applies for WHERE and JOIN clauses, as well as for checks on FOREIGN KEY constraints. I.e. the database was telling me string were equivalent and the constraint passed. Therefore I assumed that they actually were exactly equal. But that was false. DATALENGTH of one field = 10, while the DATALENGTH of the other = 8.

EF6 would correctly compose the SQL query to pull the foreign key related fields and I would see them both in the generated Sql query and in the results. However, EF6 would silently fail when loading the Navigation Properties because .NET does not consider those strings equal. Watch out for whitespace in string-type foreign key fields!.

Method 6

This article helped me.

In sum :

Install-Package Microsoft.EntityFrameworkCore.Proxies

In Startup.cs

using Microsoft.EntityFrameworkCore;

public void ConfigureServices(IServiceCollection services)
        {
              ...
            services.AddDbContext<MyDbContext>(builder =>
            {
                builder.UseLazyLoadingProxies(); // <-- add this
            }, ServiceLifetime.Singleton);

Method 7

This is a variant of Keytrap‘s answer. Using .NET 6 and EF Core 6, I created a ContextPartials.cs for any custom configurations that I don’t want EF’s Scaffold command to overwrite:

Required Package:

Install-Package Microsoft.EntityFrameworkCore.Proxies

Code (ContextPartials.cs):
// NOTE:  I am not using the new file-scoped namespace on purpose
namespace DataAccess.Models.MyDatabase
{
    // NOTE:  This is a partial outside of the generated file from Scaffold-DbContext
    public partial class MyDatabaseContext
    {
        // NOTE:  This enables foreign key tables to become accessible
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder.UseLazyLoadingProxies();
    }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x