为什么EF导航属性返回null?

时间:2015-03-26 06:49:56

标签: c# asp.net asp.net-mvc entity-framework

我有两个型号 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; }
}

我执行此代码

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

第一行在导航属性CalculationTypes上返回null enter image description here

第二行返回空集合。enter image description here为什么?

更新 快照数据库 enter image description here enter image description here 项目链接https://github.com/wkololo4ever/Stankin

添加了计算

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

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

6 个答案:

答案 0 :(得分:4)

试试这个:

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

如果将DbContext.Configuration.ProxyCreationEnabled设置为false,则除非在父对象上调用Include方法,否则DbContext将不会加载某些父对象的子对象。将DbContext.Configuration.LazyLoadingEnabled设置为true或false将不会对其行为产生任何影响。

如果将DbContext.Configuration.ProxyCreationEnabled设置为true,则会自动加载子对象,并且DbContext.Configuration.LazyLoadingEnabled值将控制何时加载子对象。

我认为这是个问题:

  

编辑:3)您确定数据库中有数据吗?   从Indicator到IndicatorGroup的外键具有该值   具体记录?我这样说是因为价值&#34; null&#34;是有效的   根本没有数据。

     

P.S。如果您没有在指示器上看到外键,则调用   &#34; IndicatorGroupId&#34;,可能有一个&#34; IndicatorId&#34;在桌子上   &#34; IndicatorGroup&#34;,在这种情况下 - 从您提供的名称 -   您的数据库配置错误,您需要使用流畅的语法   或指示EF如何制作外键的数据属性。

尝试这样做并确保修正外键。

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; }
}

答案 1 :(得分:2)

1)是否启用了延迟加载?如果没有,您需要使用&#39; .Include&#39;明确加载导航属性。语法。

2)你确定EF应该能够检测到这种关系吗?您使用Code First还是Database First?

编辑:3)您确定数据库中是否有数据,并且从Indicator到IndicatorGroup的外键具有该特定记录的值?我这样说是因为价值&#34; null&#34;如果根本没有数据,则有效。

P.S。如果您没有在指示器上看到名为&#34; IndicatorGroupId&#34;的外键,则可能存在&#34; IndicatorId&#34;在表格&#34; IndicatorGroup&#34;,在这种情况下 - 从您提供的名称 - 您的数据库配置错误,您将需要使用流畅的语法或数据属性来指示EF如何制作外键。

答案 2 :(得分:2)

检查出来:Navigation Property With Code First 。它提到了导航属性为空的原因及其解决方案。

  

默认情况下,导航属性为null,不加载它们   默认。对于加载导航属性,我们使用“include”方法   IQuearable和这种类型的加载称为Eager loading。

     

预先加载:这是查询一种类型实体的过程   加载相关实体作为查询的一部分,它通过实现   “包括”IQueryable的方法。

答案 3 :(得分:1)

行为相同,但根本原因不同于所选答案:

如果您关闭myContext.Configuration.AutoDetectChangesEnabled

,导航属性也可以为null

非常明显,但是当我实施一些性能提升时,这就得到了我。

答案 4 :(得分:0)

我遇到了这个问题,即使存在Include语句,导航属性也没有加载。

此问题是由使用.NET的SQL Server和EF6之间的字符串比较差异引起的。我使用VARCHAR(50)字段作为customers表中的主键,也用作audit_issues表中的外键字段。我没有意识到的是,我在customers表中的键最后还有两个空格字符。我的audit_issues表中没有这些字符。

However, SQL Server will automatically pad whitespace for string comparisons。这适用于WHERE和JOIN子句,以及对FOREIGN KEY约束的检查。即数据库告诉我字符串是等效的,并且约束已通过。因此,我假设,它们实际上是完全相同的。但这是错误的。一个字段的DATALENGTH = 10,而另一个字段的DATALENGTH = 8。

EF6将正确地构成SQL查询以提取与外键相关的字段,我将在生成的Sql查询和结果中看到它们。但是,在加载导航属性时, EF6会自动失败,因为.NET不认为这些字符串相等。 当心字符串型外键字段中的空格!

答案 5 :(得分:-1)

article 帮助了我。

总而言之:

Install-Package Microsoft.EntityFrameworkCore.Proxies

Startup.cs

using Microsoft.EntityFrameworkCore;

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