ASP.NET MVC Entity Framework 代码优先:没有错误,但表格未正确填充
ASP.NET MVC Entity Framework code-first: no errors but tables aren't populated correctly
我目前正在使用 MVC4 Entity Framework 制作票务系统。我已经在 SQL 服务器中填充了 tables,但只有几列不正确。首先,我想为代码量道歉,但它们都是参考所必需的!
我只希望人们检查我是否正确映射了我的模型,因为在图像 (1) 中缺少一些值。
请务必查看下面提供的两张图片,以便更清楚地了解我要完成的工作。
图像 (1) Here 显示了我希望我的 table 的样子,并显示了我的每个 类.[=22 的所有主键和外键=]
这张图片(2)Here显示了我的实体图
所以我的理想情况是:
用户可以创建多张票,他们只能将它们分配给一个管理员(这解决了票上的问题)。
每个工单将由 TicketID 标识,因此在 Admin 上 table 它应该具有 AdminID、UserID(提交工单的人)、TicketID 和 AdminRole。
每个 AdminID 可以分配给一个用户,但并非所有用户都必须分配给一个 AdminID
DepotID、DepartmentID 和类别非常简单。
DepotID和DepartmentID必须分配给一个用户,每个用户只能有1个DepotID和DepartmentID
必须为每张票分配 CategoryID,因此每张票只能有一个 CategoryID
User.cs
public class User
{
public int UserID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string LastName { get; set; }
[StringLength(50, MinimumLength = 1, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
// public int AdministratorID { get; set; }
// [ForeignKey("AdministratorID")]
// public virtual Administrator Administrator { get; set; }
public int AdminID { get; set; }
[ForeignKey("AdminID")]
public virtual Administrator Administrator { get; set; }
public int DepartmentID { get; set; }
[ForeignKey("DepartmentID")]
public virtual Department Department { get; set; }
public int DepotID { get; set; }
[ForeignKey("DepotID")]
public virtual Depot Depot { get; set; }
public int TicketID { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
}
Ticket.cs
public class Ticket
{
public string Issue { get; set; }
[DisplayFormat(NullDisplayText = "No Priority")]
public Priority? Priority { get; set; }
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public int TicketID { get; set; }
public int AdminID { get; set; }
public virtual ICollection<Administrator> Administrators { get; set; }
public int UserID { get; set; }
//[ForeignKey("TicketID")]
public virtual User User { get; set; }
}
Depot.cs
public class Depot
{
public int DepotID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Department.cs
public class Department
{
public int DepartmentID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Category.cs
public class Category
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CategoryID { get; set; }
public string Title { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
}
Administrator.cs
public class Administrator
{
[Key, ForeignKey("User")]
public int UserID { get; set; }
public int AdminID { get; set; }
public int TicketID { get; set; }
[StringLength(50)]
public string AdminRole { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
public virtual User User { get; set; }
}
Configuration.cs(种子法)
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(RecreationalServicesTicketingSystem.DAL.IssueContext context)
{
var departments = new List<Department>
{
new Department { DepartmentID = 1, Name = "IT"},
new Department { DepartmentID = 2, Name = "Admin" },
new Department { DepartmentID = 3, Name = "Human Resources"},
new Department { DepartmentID = 4, Name = "Mechanics" },
new Department { DepartmentID = 5, Name = "Directors" },
new Department { DepartmentID = 6, Name = "Operations"}
};
departments.ForEach(s => context.Departments.AddOrUpdate(p => p.Name, s));
context.SaveChanges();
var depots = new List<Depot>
{
new Depot { DepotID = 1, Name = "Porana"},
new Depot { DepotID = 2, Name = "Far North"},
};
depots.ForEach(s => context.Depots.AddOrUpdate(p => p.Name, s));
context.SaveChanges();
var users = new List<User>
{
new User { FirstMidName = "Jason", LastName = "Wan",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1, DepotID = 1},
new User { FirstMidName = "Andy", LastName = "Domagas",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1,DepotID = 1},
new User { FirstMidName = "Denis", LastName = "Djohar",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1 ,DepotID = 1},
new User { FirstMidName = "Christine", LastName = "West",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1, DepotID = 1},
};
users.ForEach(s => context.Users.AddOrUpdate(p => p.FirstMidName, s));
context.SaveChanges();
users.ForEach(s => context.Users.AddOrUpdate(p => p.LastName, s));
context.SaveChanges();
var administrator = new List<Administrator>
{
new Administrator {AdminID = 1, AdminRole = "Administrator LVL1", User = users.Single ( s => s.UserID == 1),
Tickets = new List<Ticket>() },
new Administrator {AdminID = 2, AdminRole = "Administrator LVL2", User = users.Single ( s => s.UserID == 2),
Tickets = new List<Ticket>() },
new Administrator {AdminID = 3, AdminRole = "Administrator LVL3", User = users.Single ( s => s.UserID == 3),
Tickets = new List<Ticket>() }
};
administrator.ForEach(s => context.Administrators.AddOrUpdate(p => p.AdminID, s));
context.SaveChanges();
var categories = new List<Category>
{
new Category {CategoryID = 0001, Title = "Desktop"},
new Category {CategoryID = 0002, Title = "Mobile"},
new Category {CategoryID = 0003, Title = "Menzits"},
new Category {CategoryID = 0004, Title = "XMPRO"},
new Category {CategoryID = 0005, Title = "Con-X"},
new Category {CategoryID = 0006, Title = "Promapp"},
new Category {CategoryID = 0007, Title = "QGIS"},
};
categories.ForEach(s => context.Categories.AddOrUpdate(p => p.Title, s));
context.SaveChanges();
var tickets = new List<Ticket>
{
new Ticket {
UserID = users.Single(s => s.LastName == "Wan").UserID,
CategoryID = categories.Single(c => c.Title == "Con-X" ).CategoryID,
Issue = ("Test Error NEW TEST"),
AdminID = 1,
Priority = Priority.High
},
new Ticket {
UserID = users.Single(s => s.LastName == "Wan").UserID,
CategoryID = categories.Single(c => c.Title == "Desktop" ).CategoryID,
Issue = ("Test Error 2"),
AdminID = 2,
Priority = Priority.Med
},
};
foreach (Ticket e in tickets)
{
var ticketInDataBase = context.Tickets.Where(
s =>
s.User.UserID == e.UserID &&
s.Category.CategoryID == e.CategoryID).SingleOrDefault();
if (ticketInDataBase == null)
{
context.Tickets.Add(e);
}
}
context.SaveChanges();
}
}
IssueContext.cs
public class IssueContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Ticket> Tickets { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Administrator> Administrators { get; set; }
public DbSet<Depot> Depots { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Ticket>()
.HasMany(c => c.Administrators).WithMany(i => i.Tickets)
.Map(t => t.MapLeftKey("TicketID")
.MapRightKey("AdministratorID")
.ToTable("AdministratorsTickets"));
modelBuilder.Entity<Administrator>()
.HasKey(e => e.UserID);
modelBuilder.Entity<User>()
.HasOptional(s => s.Administrator) // Mark StudentAddress is optional for Student
.WithRequired(ad => ad.User); // Create inverse relationship
}
}
第一注:
您的 Administrator
实体映射不正确。您将 UserId 标记为 PrimaryKey,因此当一个实体插入 Administrator table 时,它会自动将 UserId 设置为新身份,因此在您的图片中您会看到 UserId 逐渐增加.相反,您应该将您的 AdminID 标记为主键:
[Key]
public int AdminID { get; set; }
[ForeignKey("User")]
public int UserID { get; set; }
您还应该将用户实体的用户 ID 标记为主键:
[Key]
public int UserID { get; set; }
第二个注意事项:
您的管理员和用户使用一对多关系映射到工单,这意味着1个管理员有X个工单,1个用户有Y个工单。这意味着,Ticket table 包含 Administrator 实体和 User 实体的外键:您图片中的 AdminID 和 UserID。你可以在你的照片上看到它。如果您在两个 类 中都留下 TicketId,那将意味着您拥有 一对一 关系以及 一对多 关系真的很奇怪,不会工作。因此,您需要从您的用户和管理员 tables
中完全删除 TicketId
第三个注意事项:
您还需要从您的 Ticket 实体添加对用户和管理员的直接引用,为每个实体添加 [ForeignKey]
属性并指定您用作它们的外键的 属性。您还需要删除 Administrators 集合,因为如果您以这种方式保留它,您的关系将是 多对多:
public class Ticket
{
public int TicketID { get; set; }
public string Issue { get; set; }
[DisplayFormat(NullDisplayText = "No Priority")]
public Priority? Priority { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public int CategoryID { get; set; }
[ForeignKey("AdminID")]
public Administrator Admin { get; set; }
public int AdminID { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
public int UserID { get; set; }
}
第四注:
此外,您在用户和管理员之间具有必需-可选的一对一关系,其映射方式如下:
您的 Administrator 实体有 int UserId
,但您的 User 实体没有 AdministratorId,Entity Framework 将从 Administrator 端正确映射此关系。如果您像现在一样保留循环引用 - Administrator 有 UserId 而 User 有 AdministratorId - 它会导致很多问题,因为据我所知,EF 不以正确的方式支持它。
您应该仔细阅读有关生成数据库架构的 Entity Framework 文档,否则您将无法将 SQL 架构转换为正确的 EF 实体:
Entity Framework中的数据注释:
https://msdn.microsoft.com/en-us/data/jj591583
Configuring/Mapping 使用 Fluent 的属性和类型 API
我目前正在使用 MVC4 Entity Framework 制作票务系统。我已经在 SQL 服务器中填充了 tables,但只有几列不正确。首先,我想为代码量道歉,但它们都是参考所必需的!
我只希望人们检查我是否正确映射了我的模型,因为在图像 (1) 中缺少一些值。
请务必查看下面提供的两张图片,以便更清楚地了解我要完成的工作。
图像 (1) Here 显示了我希望我的 table 的样子,并显示了我的每个 类.[=22 的所有主键和外键=]
这张图片(2)Here显示了我的实体图 所以我的理想情况是: 用户可以创建多张票,他们只能将它们分配给一个管理员(这解决了票上的问题)。
每个工单将由 TicketID 标识,因此在 Admin 上 table 它应该具有 AdminID、UserID(提交工单的人)、TicketID 和 AdminRole。
每个 AdminID 可以分配给一个用户,但并非所有用户都必须分配给一个 AdminID
DepotID、DepartmentID 和类别非常简单。 DepotID和DepartmentID必须分配给一个用户,每个用户只能有1个DepotID和DepartmentID
必须为每张票分配 CategoryID,因此每张票只能有一个 CategoryID
User.cs
public class User
{
public int UserID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string LastName { get; set; }
[StringLength(50, MinimumLength = 1, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
// public int AdministratorID { get; set; }
// [ForeignKey("AdministratorID")]
// public virtual Administrator Administrator { get; set; }
public int AdminID { get; set; }
[ForeignKey("AdminID")]
public virtual Administrator Administrator { get; set; }
public int DepartmentID { get; set; }
[ForeignKey("DepartmentID")]
public virtual Department Department { get; set; }
public int DepotID { get; set; }
[ForeignKey("DepotID")]
public virtual Depot Depot { get; set; }
public int TicketID { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
}
Ticket.cs
public class Ticket
{
public string Issue { get; set; }
[DisplayFormat(NullDisplayText = "No Priority")]
public Priority? Priority { get; set; }
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public int TicketID { get; set; }
public int AdminID { get; set; }
public virtual ICollection<Administrator> Administrators { get; set; }
public int UserID { get; set; }
//[ForeignKey("TicketID")]
public virtual User User { get; set; }
}
Depot.cs
public class Depot
{
public int DepotID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Department.cs
public class Department
{
public int DepartmentID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Category.cs
public class Category
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CategoryID { get; set; }
public string Title { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
}
Administrator.cs
public class Administrator
{
[Key, ForeignKey("User")]
public int UserID { get; set; }
public int AdminID { get; set; }
public int TicketID { get; set; }
[StringLength(50)]
public string AdminRole { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
public virtual User User { get; set; }
}
Configuration.cs(种子法)
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(RecreationalServicesTicketingSystem.DAL.IssueContext context)
{
var departments = new List<Department>
{
new Department { DepartmentID = 1, Name = "IT"},
new Department { DepartmentID = 2, Name = "Admin" },
new Department { DepartmentID = 3, Name = "Human Resources"},
new Department { DepartmentID = 4, Name = "Mechanics" },
new Department { DepartmentID = 5, Name = "Directors" },
new Department { DepartmentID = 6, Name = "Operations"}
};
departments.ForEach(s => context.Departments.AddOrUpdate(p => p.Name, s));
context.SaveChanges();
var depots = new List<Depot>
{
new Depot { DepotID = 1, Name = "Porana"},
new Depot { DepotID = 2, Name = "Far North"},
};
depots.ForEach(s => context.Depots.AddOrUpdate(p => p.Name, s));
context.SaveChanges();
var users = new List<User>
{
new User { FirstMidName = "Jason", LastName = "Wan",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1, DepotID = 1},
new User { FirstMidName = "Andy", LastName = "Domagas",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1,DepotID = 1},
new User { FirstMidName = "Denis", LastName = "Djohar",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1 ,DepotID = 1},
new User { FirstMidName = "Christine", LastName = "West",
EnrollmentDate = DateTime.Parse("2016-02-18"), DepartmentID = 1, DepotID = 1},
};
users.ForEach(s => context.Users.AddOrUpdate(p => p.FirstMidName, s));
context.SaveChanges();
users.ForEach(s => context.Users.AddOrUpdate(p => p.LastName, s));
context.SaveChanges();
var administrator = new List<Administrator>
{
new Administrator {AdminID = 1, AdminRole = "Administrator LVL1", User = users.Single ( s => s.UserID == 1),
Tickets = new List<Ticket>() },
new Administrator {AdminID = 2, AdminRole = "Administrator LVL2", User = users.Single ( s => s.UserID == 2),
Tickets = new List<Ticket>() },
new Administrator {AdminID = 3, AdminRole = "Administrator LVL3", User = users.Single ( s => s.UserID == 3),
Tickets = new List<Ticket>() }
};
administrator.ForEach(s => context.Administrators.AddOrUpdate(p => p.AdminID, s));
context.SaveChanges();
var categories = new List<Category>
{
new Category {CategoryID = 0001, Title = "Desktop"},
new Category {CategoryID = 0002, Title = "Mobile"},
new Category {CategoryID = 0003, Title = "Menzits"},
new Category {CategoryID = 0004, Title = "XMPRO"},
new Category {CategoryID = 0005, Title = "Con-X"},
new Category {CategoryID = 0006, Title = "Promapp"},
new Category {CategoryID = 0007, Title = "QGIS"},
};
categories.ForEach(s => context.Categories.AddOrUpdate(p => p.Title, s));
context.SaveChanges();
var tickets = new List<Ticket>
{
new Ticket {
UserID = users.Single(s => s.LastName == "Wan").UserID,
CategoryID = categories.Single(c => c.Title == "Con-X" ).CategoryID,
Issue = ("Test Error NEW TEST"),
AdminID = 1,
Priority = Priority.High
},
new Ticket {
UserID = users.Single(s => s.LastName == "Wan").UserID,
CategoryID = categories.Single(c => c.Title == "Desktop" ).CategoryID,
Issue = ("Test Error 2"),
AdminID = 2,
Priority = Priority.Med
},
};
foreach (Ticket e in tickets)
{
var ticketInDataBase = context.Tickets.Where(
s =>
s.User.UserID == e.UserID &&
s.Category.CategoryID == e.CategoryID).SingleOrDefault();
if (ticketInDataBase == null)
{
context.Tickets.Add(e);
}
}
context.SaveChanges();
}
}
IssueContext.cs
public class IssueContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Ticket> Tickets { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Administrator> Administrators { get; set; }
public DbSet<Depot> Depots { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Ticket>()
.HasMany(c => c.Administrators).WithMany(i => i.Tickets)
.Map(t => t.MapLeftKey("TicketID")
.MapRightKey("AdministratorID")
.ToTable("AdministratorsTickets"));
modelBuilder.Entity<Administrator>()
.HasKey(e => e.UserID);
modelBuilder.Entity<User>()
.HasOptional(s => s.Administrator) // Mark StudentAddress is optional for Student
.WithRequired(ad => ad.User); // Create inverse relationship
}
}
第一注:
您的 Administrator
实体映射不正确。您将 UserId 标记为 PrimaryKey,因此当一个实体插入 Administrator table 时,它会自动将 UserId 设置为新身份,因此在您的图片中您会看到 UserId 逐渐增加.相反,您应该将您的 AdminID 标记为主键:
[Key]
public int AdminID { get; set; }
[ForeignKey("User")]
public int UserID { get; set; }
您还应该将用户实体的用户 ID 标记为主键:
[Key]
public int UserID { get; set; }
第二个注意事项:
您的管理员和用户使用一对多关系映射到工单,这意味着1个管理员有X个工单,1个用户有Y个工单。这意味着,Ticket table 包含 Administrator 实体和 User 实体的外键:您图片中的 AdminID 和 UserID。你可以在你的照片上看到它。如果您在两个 类 中都留下 TicketId,那将意味着您拥有 一对一 关系以及 一对多 关系真的很奇怪,不会工作。因此,您需要从您的用户和管理员 tables
中完全删除 TicketId第三个注意事项:
您还需要从您的 Ticket 实体添加对用户和管理员的直接引用,为每个实体添加 [ForeignKey]
属性并指定您用作它们的外键的 属性。您还需要删除 Administrators 集合,因为如果您以这种方式保留它,您的关系将是 多对多:
public class Ticket
{
public int TicketID { get; set; }
public string Issue { get; set; }
[DisplayFormat(NullDisplayText = "No Priority")]
public Priority? Priority { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public int CategoryID { get; set; }
[ForeignKey("AdminID")]
public Administrator Admin { get; set; }
public int AdminID { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
public int UserID { get; set; }
}
第四注:
此外,您在用户和管理员之间具有必需-可选的一对一关系,其映射方式如下:
您的 Administrator 实体有 int UserId
,但您的 User 实体没有 AdministratorId,Entity Framework 将从 Administrator 端正确映射此关系。如果您像现在一样保留循环引用 - Administrator 有 UserId 而 User 有 AdministratorId - 它会导致很多问题,因为据我所知,EF 不以正确的方式支持它。
您应该仔细阅读有关生成数据库架构的 Entity Framework 文档,否则您将无法将 SQL 架构转换为正确的 EF 实体:
Entity Framework中的数据注释:
https://msdn.microsoft.com/en-us/data/jj591583
Configuring/Mapping 使用 Fluent 的属性和类型 API