我有两个具有一对多关系的实体,如下所示:
客户1 ...... *预订
public class Customer
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public List<Booking> Bookings { get; set; }
}
public class Booking
{
[Key]
public int Id { get; set; }
public string Title{ get; set; }
public DateTime BookingDate { get; set; }
public int? CustomerId { get; set; }
public Customer Customer { get; set; };
}
如果_context是DbContext,则后面的两个查询最终会出现循环依赖。
_context.Customers.Include(x=> x.Bookings).ToList();
OR
_context.Bookings.Include(x=> x.Customer).ToList();
问题是如果我们必须在B的查询中包含实体A,我们如何查询这些相互依赖的关系,反之亦然?
答案 0 :(得分:0)
您可以使用System.ComponentModel.DataAnnotations.Schema命名空间中定义的ForeignKey属性。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Microsoft.EntityFrameworkCore;
namespace ParentChild
{
public class Customer
{
[Key]
public int? Id { get; set; }
public string Name { get; set; }
public virtual List<Booking> Bookings { get; set; }
}
public class Booking
{
[Key]
public int? Id { get; set; }
public string Title { get; set; }
public DateTime? BookingDate { get; set; }
public int? CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual Customer Customer { get; set; }
}
public class ParentChildDbContext : Microsoft.EntityFrameworkCore.DbContext
{
public ParentChildDbContext(String connectionString)
{
ConnectionString = connectionString;
}
public String ConnectionString { get; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConnectionString);
base.OnConfiguring(optionsBuilder);
}
public DbSet<Customer> Customer { get; set; }
public DbSet<Booking> Booking { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var dbContext = new ParentChildDbContext("server=(local);database=ParentChild;integrated security=yes;");
var data = dbContext.Customer.Include(p => p.Bookings).ToList();
Console.WriteLine("Customer: {0}, Bookings: {1}", data.First().Name, data.First().Bookings.Count);
Console.ReadKey();
}
}
}
另外,我为此测试创建了一个数据库:
create database ParentChild
go
use ParentChild
go
create table Customer
(
Id int not null identity(1, 1),
Name varchar(50) not null
)
create table Booking
(
Id int not null identity(1, 1),
Title varchar(50) not null,
BookingDate datetime not null,
CustomerId int not null
)
go
insert into Customer values ('Parent')
go
insert into Booking values ('First booking', getdate(), 1)
go
输出结果:
客户:家长,预订:1
答案 1 :(得分:0)
在我使用Asp.Net Core的情况下,上述问题的一个可能解决方案是告诉MVC选项如下处理引用循环:
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
我已经与EF核心团队一起提出issue来回答是否应该在消费者端处理参考循环,或者应该由EF Core处理。一旦得到答复,将更新答案。