【问题标题】:EF Core 3.1.4 Navigation property returning null in One-To-One relationshipEF Core 3.1.4 导航属性在一对一关系中返回 null
【发布时间】:2021-04-20 09:12:29
【问题描述】:

我遇到了一个问题,即导航属性在 EF Core 3.1.4 中的一对一关系中始终返回 null。

我的模型结构如下:

    public class UserCredential
    {
        public Guid Id { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public byte[] Salt { get; set; }
        public bool IsLocked { get; set; }
        public bool IsDeleted { get; set; }   
        public DateTime CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public DateTime? DeletedDate { get; set; }

        public UserProfile UserProfile { get; set; }
    }

    public class UserProfile
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
        public string Suffix { get; set; }
        public bool IsDeleted { get; set; }
        public List<Address> Addresses {get;set;}
        public DateTime DOB { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public DateTime? DeletedDate { get; set; }

        public Guid UserCredentialId { get; set; }
        public UserCredential UserCredential { get; set; }
    }

根据我的理解,这应该足以让 EF Core 推断出一对一的关系。但它没有用,所以我在我的 dbContext 中定义了这样的关系:

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<UserProfile>(entity =>
            {
                entity.HasOne(up => up.UserCredential)
                    .WithOne(uc => uc.UserProfile)
                    .HasForeignKey<UserProfile>( up => up.UserCredentialId);
            });
        }

我检查了数据库,并且在表中定义了来自 UserProfile -> UserCredentials 的外键。同样,两个表都有 Id 作为主键。

如果我将数据发布到“addUser”端点,它将被正确添加到数据库中。

{
    "username": "test3",
    "password": "password123",
    "UserProfile":{
        "FirstName": "John",
        "LastName": "Doe"
    }
}

Db Screenshot

但是,我的模型中的“UserProfile”始终为空。

System.NullReferenceException: '对象引用未设置为 一个对象的实例。 IronCarp.Identity.Models.UserCredential.UserProfile.get 返回 null。

我正在使用存储库与数据库交互,返回我的数据/模型的方法似乎很简单。

        private async Task<UserCredential> GetUserCredentials(string username)
        {
            return await context.UserCredentials.Where(u => u.Username == username).FirstOrDefaultAsync();
        }

感谢任何帮助,我不确定我缺少什么,谢谢!

【问题讨论】:

    标签: .net-core entity-framework-core


    【解决方案1】:

    尝试在 linkq 中包含导航属性,试试这样:

    private async Task<UserCredential> GetUserCredentials(string username)
            {
                return await context.UserCredentials.Include(x => x.UserProfile).Where(u => u.Username == username).FirstOrDefaultAsync();
            }
    

    【讨论】:

    • 是的,成功了!谢谢你!如果我需要返回相关数据,那是我应该采用的模式吗?我的印象是 ef core 会推断关系并自动返回。
    • 我希望您阅读下面的文章以了解热切加载。 docs.microsoft.com/en-us/ef/ef6/querying/related-data
    • 我做了,但由于我的代表很低,直到我的代表上升后才会显示。
    【解决方案2】:

    对我来说,这个问题在我的集成测试中间歇性发生。

    原来是因为我错误地将 EF Core DbContext 注册为 Transient 而不是 Scoped

    Services.AddDbContext<SubscriptionsContext>(
                options => options.UseNpgsql(appConfig.DatabaseConnectionString,
                    optionsBuilder => optionsBuilder.EnableRetryOnFailure(3)), ServiceLifetime.Transient);
    

    应该是:

    Services.AddDbContext<SubscriptionsContext>(
                options => options.UseNpgsql(appConfig.DatabaseConnectionString,
                    optionsBuilder => optionsBuilder.EnableRetryOnFailure(3)), ServiceLifetime.Scoped);
    

    如果你查看AddDbContext()扩展方法的默认参数,它总是Scoped

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 2022-07-18
      • 2015-05-30
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      相关资源
      最近更新 更多