Entity Framework 6.4 + PostgreSQL关系一对一单边不包含实体
Entity Framework 6.4 + PostgreSQL Relationship One-to-One Unilateral don't include entity
我有这个代码和关系:
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, name,...
地址 -> 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
我使用这个结构来做这个急切加载的查询。我也尝试使用急切加载进行另一个查询,但使用其他实体进行查询,但我遇到了同样的问题。
地址在用户中不是强制性的,但在我的例子中,用户必须在地址中。所以,我想打电话给一个用户,而那个用户就在那个地址上。
仅通过属性设置关系(外键)不足以获取查询的相关数据。出于性能原因,作为默认行为,EF 不会将 return 相关对象作为查询的一部分。您必须明确指定要 return 作为查询的一部分的相关对象。
您可以在下面找到示例代码,以便在查询 User 对象时也可以获取 Address 详细信息(您创建查询的地方,您必须有 ApplicationContext
class 的实例,我假设变量的名称是 dbContext):
dbContext.User.Include(u => u.Address).ToList();
上面的代码使用 Linq 扩展中的 ToList() 方法。如果你使用 Microsoft.EntityFrameworkCore 包,你还可以编写上面代码的异步版本,如下所示:
dbContext.User.Include(u => u.Address).ToListAsync();
编辑:
对您的问题进行了 2 次新编辑,我也在编辑我的答案。
首先,更新你的 OnModelCreating 方法如下,基本上,我们删除 HasForeignKey 方法(因为你已经使用属性定义了这种关系在你的 class) 上并且还明确指定 WithOne 方法与 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);
我有这个代码和关系:
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, name,...
地址 -> 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
我使用这个结构来做这个急切加载的查询。我也尝试使用急切加载进行另一个查询,但使用其他实体进行查询,但我遇到了同样的问题。
地址在用户中不是强制性的,但在我的例子中,用户必须在地址中。所以,我想打电话给一个用户,而那个用户就在那个地址上。
仅通过属性设置关系(外键)不足以获取查询的相关数据。出于性能原因,作为默认行为,EF 不会将 return 相关对象作为查询的一部分。您必须明确指定要 return 作为查询的一部分的相关对象。
您可以在下面找到示例代码,以便在查询 User 对象时也可以获取 Address 详细信息(您创建查询的地方,您必须有 ApplicationContext
class 的实例,我假设变量的名称是 dbContext):
dbContext.User.Include(u => u.Address).ToList();
上面的代码使用 Linq 扩展中的 ToList() 方法。如果你使用 Microsoft.EntityFrameworkCore 包,你还可以编写上面代码的异步版本,如下所示:
dbContext.User.Include(u => u.Address).ToListAsync();
编辑: 对您的问题进行了 2 次新编辑,我也在编辑我的答案。
首先,更新你的 OnModelCreating 方法如下,基本上,我们删除 HasForeignKey 方法(因为你已经使用属性定义了这种关系在你的 class) 上并且还明确指定 WithOne 方法与 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);