我遇到的问题是,在向数据库添加预留或我的测试数据时(使用Entity Framework),它在其中一个表中创建了一个空的空行。
我有3张桌子
Reservation
和Rooms
之间存在多对多关系。 ContactPerson
和Reservation
之间有一对多。
我使用代码优先方法。
预订类:
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; }
}
会议室班级:
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
}
ContactPerson 类:
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
课程:
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
类插入测试数据。
配置:
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
表看起来不错,Rooms
表看起来也不错,共享表ReservationRoom
看起来也不错。问题是ContactPerson
表,当我添加房间或预订时,它会在添加正确的联系人之前添加一个空行。
您可以在此屏幕截图中看到它:
您可以在运行命令add-migration InitialCreate
和update-database
之后看到结果。
当使用以下方法尝试添加我在应用程序中创建的预留时,也会发生这种情况:
public void CreateReservation(Reservation item)
{
Reservations.Add(item);
}
预订表如下所示:
在这里,您可以看到它指向由于某种原因创建的空空行。
希望有人可以告诉我这里可能有什么问题。我用了很多天试图重新配置模型和东西,但似乎没有一个对我有效。
答案 0 :(得分:1)
您遇到此类问题,因为您的Reservation
构造函数实现不正确:
public Reservation()
{
Room = new List<Room>();
ContactPerson = new ContactPerson();
}
如此实施,您可以自动为预订创建新的ContactPerson
。然后,在Reservation
方法中保存Seed
时,它将不会使用您在ContactPerson
方法中创建的Seed
人。
将构造函数更改为:
public Reservation()
{
Room = new List<Room>();
}
然后在您的Seed
方法中,因为每个Reservation
必须有ContactPerson
,所以您应该在创建附加ContactPerson
之前插入Reservation
:
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
一次,但要实现这一点,您需要避免使用像您一样的常量外键。