ASP.net MVC 4 EF5中的代码优先方法混淆

时间:2013-11-25 21:15:33

标签: c# asp.net asp.net-mvc entity-framework

在过去的10个小时里,我一直在努力寻找并研究实现关系代码第一个数据库结构和类架构的最佳方法。

不幸的是,到目前为止,ASP和Google已经打败了我!

我会附上一个UML图来更好地解释我想要系统做什么,我真的只是在寻找我应该采取的方法的解释,在哪里保留某些功能,如果我需要创建额外的类视图模型,域模型,如何将所有这些链接到数据库上下文,我是否需要自己创建所有CRUD实现?等等。

(我使用ArrayList,因为我来自Java背景并且知道最好,我一直在阅读ICollections和IEnumerables但是无法决定使用哪一个?

UML Diagram

从我之前的尝试到目前为止我已尝试过:

  • 针对所有DbContextDbSetRoom类实施Bunk类的单个类,其中包含Booking个。
  • 每个“实体”的单个域类(这是正确的术语吗?)存储类似于上面的类数据,我已经设法在add-migrations的帮助下从这些生成数据库但是方式它使用Room链接BunkICollection类似乎没有提供任何方法来访问Room ICollection中与Room.Bunks相关联的数据块从DB中检索上下铺时。
  • 我还有RoomHelperBunkHelper个类,它们使用LINQ语句尝试手动检索各种数据以及标准的CRUD方法。这似乎让人感到困惑,让我觉得我可能会遗漏那些为我自动生成的东西?

这是很多,但我真的很挣扎,任何帮助都非常感激:)

正如有些人在下方要求的是我创建的代码

Bunk.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using TestApplication.Models.Enums;

namespace TestApplication.Models
{
    public class Bunk
    {
        [Key]
        public Int32 BunkId { get; set; }
        public BunkStatus BunkStatus { get; set; }
    }
}

Room.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using TestApplication.Models.Enums;

namespace TestApplication.Models
{
    public class Room
    {
        [Key]
        public Int32 RoomId { get; set; }
        public String RoomName { get; set; }
        public Gender RoomGender { get; set; }
        public RoomStatus RoomStatus { get; set; }
        public ICollection<Bunk> Bunks { get; set; }
    }
}

DatabaseContext.cs

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace TestApplication.Models
{
    public class DatabaseContext : DbContext
    {
        public DbSet<Room> Rooms { get; set; }
        public DbSet<Bunk> Bunks { get; set; }
    }
}

此代码生成了以下数据库结构,不允许我访问Room.Bunks.All()(作为我误解的概念的示例用法)

db preview

2 个答案:

答案 0 :(得分:0)

这些是您需要的课程:

public class Room
{
    [Key]
    public int RoomId { get; set; }

    public string RoomName { get; set; }

    public GenderEnum Gender { get; set; }

    public RoomStatusEnum RoomStatus { get; set; }

    public virtual ICollection<Bunk> Bunks { get; set; }

    // convenience
    public virtual ICollection<Booking> Bookings { get; set; }
}

public class Bunk
{
    [Key]
    public int BunkId { get; set; }

    public BunkStatusEnum BunkStatus { get; set; }

    [ForeignKey("Room")]
    public int RoomId { get; set; }
    public virtual Room Room { get; set; }

    // convenience
    public virtual ICollection<Booking> Bookings { get; set; }
}

public class Booking
{
    [Key]
    public int BookingId { get; set; }

    [ForeignKey("UserProfile")]
    public int UserProfileId { get; set; }
    public UserProfile UserProfile { get; set; }

    [ForeignKey("Bunk")]
    public int BunkId { get; set; }
    public Bunk Bunk { get; set; }

    public int Duration { get; set; }

    [ForeignKey("Preferred_Room")]
    public int RoomId { get; set; }
    public Room Preferred_Room { get; set; }

    public Decimal Price { get; set; }

    public BookStatusEnum BookingStatus { get; set; }
}

我唯一要注意的是RoomBooking的外键。如果Bunk只能属于一个Room,那么已选择RoomBunk.Room。通过为Booking的{​​{1}}添加另一个外键,您将创建一个双重链接,这将使删除工作变得非常艰难。

答案 1 :(得分:0)

我将在上面的评论中进行扩展,因为在发布您的代码之后,您似乎确实没有将导航属性设置为虚拟。

您需要使用某种查询从数据库中获取房间对象。例如:

using (var context = new DatabaseContext()){
    var room = context.Rooms.First();
}

在上面的示例中,您将最终得到一个房间对象,但实体框架不会自动撤回所有相关实体(即Bunks)..在很多情况下,这将是过度的,在某些情况下它是不可能。您需要专门告诉实体框架您希望它带回哪些相关实体。 e.g:

using (var context = new DatabaseContext()){
    var room = context.Rooms.Include("Bunks").First();
}

在此示例中,实体框架将加载Bunks作为查询的一部分,您将能够使用语法room.Bunks()

访问Bunks。

最后,如果您喜欢这样,那么您也可以使用原始示例。您将利用称为延迟加载的功能,实体框架将仅在您第一次访问导航属性(即room.Bunks)时加载相关实体。这将需要2次调用数据库。第一次打电话来获得房间,第二次打电话给Bunks。

仅当您将ICollection属性更改为虚拟时才会起作用:

public ICollection<Bunk> Bunks { get; set; }

需要成为

public virtual ICollection<Bunk> Bunks { get; set; }

这是因为实体框架需要知道您何时首次访问Bunks集合。实体框架通过返回从Room类派生的对象而不是Room类来执行此操作,并使用在您第一次访问它时运行的代码覆盖Bunks属性。如果此属性不是虚拟的,则它无法执行此操作,因此无法正常工作