Entity Framework 添加测试数据时,在实际行之前添加一个 null 空行(保留)

Entity Framework adds a null empty row before the actually row, when adding test data (a reservation)

我有一个问题,当向数据库添加预订或我的测试数据(使用 Entity Framework)时,它在 table 之一中创建了一个空的空行。

我有 3 table

ReservationRooms 之间存在多对多关系。 ContactPersonReservation 之间存在一对多。

我正在使用代码优先方法。

预订 class:

public class Reservation
{
    public Reservation()
    {
        Room = new List<Room>();
        ContactPerson = new ContactPerson();
    }

    public int ReservationID { get; set; }
    public string ReservationNumber { get; set; }
    public DateTime CheckInDate { get; set; }
    public DateTime CheckOutDate { get; set; }
    public int ContactPersonID { get; set; }

    public virtual ContactPerson ContactPerson { get; set; }
    public virtual ICollection<Room> Room { get; set; }
}

房间 class:

public class Room
{
    public int ID { get; set; }
    public string RoomNumber { get; set; }
    public bool Occupied { get; set; }
    public bool Smoking { get; set; }
    public bool Minibar { get; set; }
    public int Beds { get; set; }
    public RoomTypeEnum? RoomType { get; set; }

    public virtual ICollection<Reservation> Reservations { get; set; }
}

public enum RoomTypeEnum
{
    Single = 0, Double = 1, Family = 2, Suite = 3
}

联系人 class:

public class ContactPerson
{
    public int ContactPersonID { get; set; }
    public string Title { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public Nationality NationalityType { get; set; }

    public virtual ICollection<Reservation> Reservations { get; set; }
}

public enum Nationality
{
    Denmark, Germany, England, France, Holland, Belgium, Norway, Sweden, Finland
}

我的DataContextclass:

public interface IDataContext
{
    DbSet<Room> Rooms { get; }
    DbSet<Reservation> Reservations { get; }
    DbSet<ContactPerson> ContactPersons { get; }
    int SaveChanges();
    void MarkAsModified(Reservation item);
    void MarkRoomAsModified(Room item);
    void CreateReservation(Reservation item);
}

public class DataContext : DbContext, IDataContext
{
    public DataContext() : base("DataContext")
    {

    }

    // DbSet to bookings
    public DbSet<Reservation> Reservations { get; set; }
    public DbSet<ContactPerson> ContactPersons { get; set; }
    public DbSet<Room> Rooms { get; set; }

    public void MarkAsModified(Reservation item)
    {
        Entry(item).State = EntityState.Modified;
    }

    public void MarkRoomAsModified(Room item)
    {
        Entry(item).State = EntityState.Modified;
    }

    public void CreateReservation(Reservation item)
    {
        Reservations.Add(item);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Reservation>()
            .HasMany(c => c.Room).WithMany(i => i.Reservations)
            .Map(t => t.MapLeftKey("ReservationID")
            .MapRightKey("RoomID")
            .ToTable("RoomReservation"));
    }
}

我正在使用迁移时生成的 Configuration class 插入测试数据。

配置:

protected override void Seed(WebApplication1.DAL.DataContext context)
{
        var reservations = new List<Reservation>
            {
                new Reservation{ReservationNumber = "123456789", CheckInDate = DateTime.Parse("2016-01-01"), CheckOutDate = DateTime.Parse("2016.01.15"), ContactPersonID = 1
                }
            };

        reservations.ForEach(b => context.Reservations.AddOrUpdate(r => r.ReservationID, b));
        context.SaveChanges();

        var contactPersons = new List<ContactPerson>
            {
                new ContactPerson{Title = "Mr" ,FirstName = "Anders",LastName = "Christensen", Email = "AndersChristensen@gmail.com", NationalityType = Nationality.Denmark, PhoneNumber = "44216731" }
            };

        contactPersons.ForEach(b => context.ContactPersons.AddOrUpdate(c => c.ContactPersonID, b));
        context.SaveChanges();

        var rooms = new List<Room>
        {
            new Room {RoomNumber = "101", Beds = 1, RoomType = RoomTypeEnum.Single, Minibar = true, Occupied = true, Smoking = false},
            new Room {RoomNumber = "102", Beds = 1, RoomType = RoomTypeEnum.Single, Minibar = true, Occupied = true, Smoking = false},
            new Room {RoomNumber = "103", Beds = 1, RoomType = RoomTypeEnum.Single, Minibar = true, Occupied = false, Smoking = false},
            new Room {RoomNumber = "104", Beds = 2, RoomType = RoomTypeEnum.Double, Minibar = true, Occupied = false, Smoking = true},
            new Room {RoomNumber = "105", Beds = 3, RoomType = RoomTypeEnum.Family, Minibar = true, Occupied = false, Smoking = false},
        };

        rooms.ForEach(b => context.Rooms.AddOrUpdate(b));
        context.SaveChanges();

        AddOrUpdateReservation(context, "101", "123456789");
        context.SaveChanges();
    }

    void AddOrUpdateReservation(DataContext context, string roomNumber, string reservationNumber)
    {
        var reservation = context.Reservations.SingleOrDefault(c => c.ReservationNumber == reservationNumber);
        var room = reservation.Room.SingleOrDefault(r => r.RoomNumber == roomNumber);
        if (room == null)
            reservation.Room.Add(context.Rooms.Single(i => i.RoomNumber == roomNumber));
    }

Reservationtable好看,Roomstable好看,分享的tableReservationRoom也好看好的。问题是 ContactPerson table,当我添加房间或预订时,它会在添加正确的联系人之前添加一个空行。

您在这张截图中看到了它:

在这里您可以看到 运行 命令后的结果,add-migration InitialCreateupdate-database

当我尝试添加我在我的应用程序中创建的预订时,使用以下方法时也会发生这种情况:

public void CreateReservation(Reservation item)
{
    Reservations.Add(item);
}

预订 table 看起来像这样:

在这里您可以看到它指向由于某种原因创建的空空行。

希望有人能告诉我这里可能出了什么问题。我花了几天时间尝试重新配置模型和东西,但 none 似乎对我有用。

您遇到此类问题是因为您的 Reservation 构造函数实现不正确:

public Reservation()
{
    Room = new List<Room>();
    ContactPerson = new ContactPerson();
}

像这样实施,您会自动为预订创建一个新的 ContactPerson。然后,在您的 Seed 方法中保存 Reservation 时,它将不会使用您在该 Seed 方法中创建的那个 ContactPerson 人。

将您的构造函数更改为:

public Reservation()
{
    Room = new List<Room>();
}

然后在你的 Seed 方法中,因为每个 Reservation 必须有一个 ContactPerson 你应该在创建附加 Reservation 之前插入 ContactPerson 像这样:

protected override void Seed(WebApplication1.DAL.DataContext context)
{
    var contactPersons = new List<ContactPerson>
        {
            new ContactPerson{Title = "Mr" ,FirstName = "Anders",LastName = "Christensen", Email = "AndersChristensen@gmail.com", NationalityType = Nationality.Denmark, PhoneNumber = "44216731" }
        };

    contactPersons.ForEach(b => context.ContactPersons.AddOrUpdate(c => c.ContactPersonID, b));
    context.SaveChanges();

    var reservations = new List<Reservation>
        {
            new Reservation{ReservationNumber = "123456789", CheckInDate = DateTime.Parse("2016-01-01"), CheckOutDate = DateTime.Parse("2016.01.15"), ContactPersonID = 1
            }
        };

    reservations.ForEach(b => context.Reservations.AddOrUpdate(r => r.ReservationID, b));
    context.SaveChanges();

    var rooms = new List<Room>
    {
        new Room {RoomNumber = "101", Beds = 1, RoomType = RoomTypeEnum.Single, Minibar = true, Occupied = true, Smoking = false},
        new Room {RoomNumber = "102", Beds = 1, RoomType = RoomTypeEnum.Single, Minibar = true, Occupied = true, Smoking = false},
        new Room {RoomNumber = "103", Beds = 1, RoomType = RoomTypeEnum.Single, Minibar = true, Occupied = false, Smoking = false},
        new Room {RoomNumber = "104", Beds = 2, RoomType = RoomTypeEnum.Double, Minibar = true, Occupied = false, Smoking = true},
        new Room {RoomNumber = "105", Beds = 3, RoomType = RoomTypeEnum.Family, Minibar = true, Occupied = false, Smoking = false},
    };

    rooms.ForEach(b => context.Rooms.AddOrUpdate(b));
    context.SaveChanges();

    AddOrUpdateReservation(context, "101", "123456789");
    context.SaveChanges();
}

我认为您也可以在方法结束时调用 SaveChanges 一次,但要使其正常工作,您需要避免像现在这样使用常量外键。