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
- 预订
- 联系人
- 房间
Reservation
和 Rooms
之间存在多对多关系。 ContactPerson
和 Reservation
之间存在一对多。
我正在使用代码优先方法。
预订 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
}
我的DataContext
class:
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));
}
Reservation
table好看,Rooms
table好看,分享的tableReservationRoom
也好看好的。问题是 ContactPerson
table,当我添加房间或预订时,它会在添加正确的联系人之前添加一个空行。
您在这张截图中看到了它:
在这里您可以看到 运行 命令后的结果,add-migration InitialCreate
和 update-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
一次,但要使其正常工作,您需要避免像现在这样使用常量外键。
我有一个问题,当向数据库添加预订或我的测试数据(使用 Entity Framework)时,它在 table 之一中创建了一个空的空行。
我有 3 table
- 预订
- 联系人
- 房间
Reservation
和 Rooms
之间存在多对多关系。 ContactPerson
和 Reservation
之间存在一对多。
我正在使用代码优先方法。
预订 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
}
我的DataContext
class:
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));
}
Reservation
table好看,Rooms
table好看,分享的tableReservationRoom
也好看好的。问题是 ContactPerson
table,当我添加房间或预订时,它会在添加正确的联系人之前添加一个空行。
您在这张截图中看到了它:
在这里您可以看到 运行 命令后的结果,add-migration InitialCreate
和 update-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
一次,但要使其正常工作,您需要避免像现在这样使用常量外键。