【问题标题】:EF6 Optional 1:1 include not workingEF6 可选 1:1 包括不工作
【发布时间】:2016-10-09 06:39:17
【问题描述】:

尝试设置基本的 EF6 可选 1:1。非常令人沮丧。我已经阅读了很多并且丢失了帖子。

我有两个实体,Guests 和 Seats,每个实体都可以单独存在,一个座位不需要一个客人,一个客人不需要一个座位。

嘉宾模特:

        public int ID { get; set; }

        public int? SeatID { get; set; }

        [Required]
        public string FirstName { get; set; }

        //Link to Seat
        public Seat Seat { get; set; }

座椅型号:

        public int ID { get; set; }

        public int? GuestID { get; set; }

        [Required]
        public string SeatNumber { get; set; }

        public bool Occupied { get { return (GuestID == null ? true : false); } }

        //Link to Guest
        public Guest Guest{ get; set; }

到这一步我遇到了很多问题。我必须将此添加到我的模型创建中才能使关系起作用:

       modelBuilder.Entity<Seat>()
            .HasOptional(g => g.Guest)
            .WithOptionalDependent(s => s.Seat);

现在我的应用程序正在运行,但是当我尝试使用 include 方法加载相关数据时,它只是空白,什么都没有。

var seats = db.Seats.Include(s => s.Guest);
            return View(seats.ToList());

在我看来,我使用

@Html.DisplayFor(modelItem => item.Guest.FirstName)

我想知道如何使 include 语句工作,最好不要延迟加载(或者即使我必须这样做)。另外,我不想有 SeatAssignment 表,我考虑过这条路。

我可以使用 Viewmodel 来实现这一点,但我不明白为什么 1:1 选项没有加载相关数据。

根据要求,这里是生成的架构...这里肯定发生了一些奇怪的事情。作为旁注,我可以使它与视图模型一起使用,但我不想这样做。

【问题讨论】:

  • 你能展示不同的流派表模式吗?
  • 将它添加到我的问题中,现在我知道它为什么不起作用但我对它是如何产生的更加困惑。

标签: c# entity-framework linq eager-loading


【解决方案1】:

您必须如下所示构建模型。

public class Guest
{
        public int GuestId { get; set; }

        [Required]
        public string FirstName { get; set; }

        //Link to Seat
        public virtual Seat Seat { get; set; }
}

public class Seat
{
        public int SeatId { get; set; }

        [Required]
        public string SeatNumber { get; set; }

        public bool Occupied { get { return (GuestID == null ? true : false); }}

        //Link to Guest
        public virtual Guest Guest{ get; set; }
}

流畅的 API 映射:

  modelBuilder.Entity<Seat>()
            .HasOptional(g => g.Guest)
            .WithOptionalDependent(s => s.Seat);

然后:

var seats = db.Seats.Include(s => s.Guest).ToList();

【讨论】:

  • 我将此标记为正确,因为它更接近我用于解决方案的内容。这两个答案都不能完全完成我想做的事情。 include 语句仍然不适用于此解决方案。我使用 Viewmodel 来显示应该与 include 语句一起使用的相关信息。感谢您的建议先生们,我能够使一些工作。两种解决方案各有千秋
  • 不客气 :)。希望你能提出自己的答案吗?
【解决方案2】:

1-0..1关系配置和你想要的方式不一样。

  1. X和Y的1-0..1关系表示XId是X的主键,XId也是Y的主键,也是外键
  2. 您请求的是 m=1 和 n=1 的 m-n 关系,因此配置应该不同。

根据上述规则,您的代码应如下所示

来宾班

public class Guest
{
    public int ID { get; set; }
    [Required]
    public string FirstName { get; set; }

    public IList<Seat> Seats { get; set; }
}

座位等级

public class Seat
{
    public int ID { get; set; }
    [Required]
    public string SeatNumber{ get; set; }

    public IList<Guest> Guests { get; set; }
}

加入表

public GuestSeat
{
     public int GuestID{get;set;}
     public int SeatID{get;set;}

     public DateTime ReservedDate{get;set;}
     // other fields goes here
}

配置

modelBuilder.Entity<GuestSeat>()
            .HasKey(gs => new {gs.GuestID,gs.SeatID})
            .ToTable("GuestSeats");
modelBuilder.Entity<GuestSeat>()
            .HasRequired(g=>g.Guest)
            .WithMany(g=>g.Seats)
            .HasForeignKey(gs =>gs.GuestID)
            .DeleteOnCascade(false);
modelBuilder.Entity<GuestSeat>()
            .HasRequired(s=>s.Seat)
            .WithMany(s=>s.Guests)
            .HasForeignKey(gs =>gs.SeatID)
            .DeleteOnCascade(false);

此解决方案提供以下内容

  1. 作为嘉宾,今天的活动可以预定A座,明天的活动可以预定B座。
  2. 客人 X 可以占用座位 A,明天客人 Y 可以占用座位 A
  3. 为确保座位在给定日期可以被一个人占用,您可以在SeatIDReservedDate 上创建唯一索引。

希望对你有帮助

【讨论】:

  • 两个答案都可以工作......但都没有完全完成我想要做的事情,也没有使 include 语句工作。
猜你喜欢
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 2016-12-29
  • 2017-03-01
  • 2014-01-28
相关资源
最近更新 更多