首页 > 解决方案 > Entity Framework 6.4 + PostgreSQL 关系一对一单边不包括实体

问题描述

我有这个代码和关系:

namespace Tequila.Models.DTOs
{
    public class ApplicationContext : DbContext
    {
        public ApplicationContext(DbContextOptions options) : base(options)
        {

        }

        public DbSet<Address> Address { get; set; }
        public DbSet<User> User { get; set; }
    }

    [Table("address")]
    public class Address
    {
        [Column("id")]
        public long AddressId { get; set; }

        [Column("user_id")]
        [ForeignKey("User")]
        public long UserId { get; set; }
        public User User { get; set; }
    }

    [Table("user")]
    public class User
    {
        [Key, Column("id")]
        public long UserId { get; set; }

        public Address Address { get; set; }
    }
} 

用户-> id,名称,...

地址-> id、地址、user_id...

当我执行此路线以查找用户和您的地址时,SQL 生成的是:

SELECT u.id, u.name, ... , u.password
  FROM user AS u
  WHERE u.id = @__Id_0
  LIMIT 1

我已经通过文档官方和社区尝试了许多其他想法,但我没有成功。

我不明白这个问题发生了什么。

编辑

我像这样在我的存储库中调用包含在上下文中

User user = context.User.Include("Address").FirstOrDefault(u => u.Id == Id);

或者

User user = context.User.Include("Address").Where(u => u.Id == Id).FirstOrDefault();

我创建了我的OnModelCreating函数

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>()
            .HasOne(e => e.Address)
            .WithOne()
            .HasForeignKey("Address");
}

我尝试了许多其他配置此功能,但我仍然没有成功。

编辑 2

这是我用来做的结构

我使用这个结构来做这个急切负载的查询。我也尝试用急切的负载进行另一个查询,但是使用其他实体,我遇到了同样的问题。

地址在用户中不是强制性的,但在我的情况下,用户必须在地址中。所以,当我打电话给一个用户时,我想打电话给一个地址,而那个用户就在那个地址上。

标签: c#postgresqlentity-framework-6

解决方案


通过属性仅设置关系(外键)不足以获取查询的相关数据。出于性能原因,作为默认行为,EF 不会将相关对象作为查询的一部分返回。您必须明确指定要作为查询的一部分返回的相关对象。

在下面您可以找到示例代码,以便在查询 User 对象时还可以获取 Address 详细信息(您创建查询的地方,您必须有一个ApplicationContext类的实例,我假设变量的名称是dbContext):

dbContext.User.Include(u => u.Address).ToList();

上面的代码使用来自 Linq 扩展的ToList()方法。如果您使用Microsoft.EntityFrameworkCore包,您还可以编写上述代码的异步版本,如下所示:

dbContext.User.Include(u => u.Address).ToListAsync();

编辑: 对您的问题进行了 2 个新的编辑,我也在编辑我的答案。

首先,如下更新您的OnModelCreating方法,基本上,我们删除HasForeignKey方法(因为您已经使用类上的属性定义了这种关系),并明确指定WithOne方法与Address实体的User属性具有一对一的关系(在Microsoft Docs上 ,如果不传递参数,您可以找到它的行为方式,很快它会说如果要使用导航属性,则必须指定它。):

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>()
        .HasOne(u => u.Address)
        .WithOne(a => a.User);
}

其次,您的查询部分如下应该可以工作:

var user = context.User.Include(u => u.Address).FirstOrDefault(u => u.Id == Id);

推荐阅读