繁体   English   中英

在查询中包括父母和孩子?

[英]Include parent and child in query?

我有两个具有一对多关系的实体,例如:

客户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();

要么

_context.Bookings.Include(x=> x.Customer).ToList();

问题是,如果必须在B的查询中包括实体A,反之亦然,我们如何查询这些相互依存的关系呢?

您可以使用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

对于我在使用Asp.Net Core时遇到的上述问题,一种可能的解决方案是告诉MVC选项来处理引用循环,如下所示:

 services.AddMvc()
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                });

我向EF核心团队提出了一个问题 ,以回答是否应该在用户端处理引用循环或应由EF Core处理引用循环。 得到答复后将更新答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM