在我的数据模型(Entity Framework 6.1.3、ASP.NET MVC 5、Code First 和现有数据库)中有两个表,“Person”和“User”共享一对一的关系。 “用户”表的PK PersonID 列又是“Person”表的PK。我希望每当创建新的用户记录时,(首先)自动创建一个 Person 记录,然后将 Person 表中的 PersonID 的值插入到新的 User 记录中。
这是 Person 表的模型代码:
[Table("Person")]
public partial class Person
{
public int PersonID { get; set; }
public virtual User User { get; set; }
}
这是用户表的模型代码:
[Table("User")]
public partial class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int PersonID { get; set; }
[Required]
[StringLength(20)]
public string Name { get; set; }
public virtual Person Person { get; set; }
}
UserController.cs 代码包括:
// POST: User/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PersonID,Name")] User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.PersonID = new SelectList(db.People, "PersonID", "PersonID", user.PersonID);
return View(user);
}
Person 表的 SQL:
CREATE TABLE [dbo].[Person](
[PersonID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL
CONSTRAINT [PK_Person_PersonID] PRIMARY KEY CLUSTERED)
用户表的SQL:
CREATE TABLE [dbo].[User](
[PersonID] [int] NOT NULL,
[Name] [nvarchar](20) NOT NULL
CONSTRAINT [PK_User_PersonID] PRIMARY KEY CLUSTERED)
ALTER TABLE [dbo].[User] WITH CHECK ADD CONSTRAINT [FK_User_Person_PersonID] FOREIGN KEY([PersonID])
REFERENCES [dbo].[Person] ([PersonID])
GO
ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_Person_PersonID]
GO
提前致谢,加拉夫。
最佳答案
你的数据库结构应该是这样的
- 表用户:(PersonID int (PK, FK), Name nvarchar(20))
- 表人 (PersonID int (PK , identity), ...)
将上述数据库结构转化为 Entity Framework 配置
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure PersonID as PK for User
modelBuilder.Entity<User>()
.HasKey(e => e.PersonID);
// Configure PersonID as FK for User
modelBuilder.Entity<Person>()
.HasRequired(p => p.User)
.WithRequired(u => u.Person);
}
如果您尝试在没有 User
的情况下单独保存 Person
,则上述配置(1-1 关系)将出错,反之亦然。
Note: I recommend to build a (1-0..1 relationship) since logically the
User
is strictly depending on the person ( weak entity) whilePerson
can exists alone without having a user. the configuration of 1:0..1 is very similar to the above configuration, the only difference is by making.HasOptional(p=>p.User)
instead of.HasRequired(p=>p.User)
现在当你创建用户实体时,你的代码应该是这样的
var user = new User(){
Name = "UserName",
Person = new Person(){
FirstName="FirstName",
LastName ="LastName",
...
}
};
db.Users.Add(user);
db.SaveChanges();
以上代码将在您创建用户对象时强制创建人员对象。
更新:针对您的情况:
我建议您创建一个 DTO对象来管理两个对象(用户和人员)的 CRUD,如下所示
public class UserDTO
{
public int Id { get; set;}
public string UserName { get;set;}
public string Password { get;set;}
public string FirstName { get; set;}
public string LastName { get; set;}
// ... any other required properties goes here ... //
}
您的 UserController.cs
代码可以在一个操作中处理创建和编辑,如下所示,只要两个 View 相同,这将允许您减少代码。
[HttpGet]
public ActionResult CreateOrEdit(int? id)
{
UserDTO user = null;
if( id!=null)
user = db.Users.Select(t=> new UserDTO {
UserName = t.UserName,
FirstName = t.Person.FirstName,
LastName = t.Person.LastName,
Id = t.Id
// ... //
}).FirstOrDefault();
else
user = new UserDTO();
return View(user);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateOrEdit(UserDTO model)
{
if(model!=null && ModelState.IsValid)
{
if(model.Id>0) // Edit
{
User user = db.Users.Include(p=>p.Person).Single(t=>t.Id == model.Id);
user.UserName = model.UserName;
user.Person.FirstName = model.FirstName;
user.Person.LastName = model.LastName;
}
else // Add
{
User user = new User
{
UserName = model.UserName,
Password = model.Password, // should be encrypted first
Person = new Person{
FirstName = model.FirstName,
LastName = model.LastName
}
};
db.Users.Add(user);
}
db.SaveChanges();
return RedirectoToAction("TargetActionGoesHere");
}
return View(model);
}
你的 View CreateOrEdit.cshtml
应该是这样的,我不会为了简单而添加 html 代码和标签
@model UserDTO
@using(Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@* To store the value of Id in hidden field*@
@Html.HiddenFor(m=>m.Id)
@Html.EditorFor(m=>m.FirstName)
@Html.EditorFor(m=>m.LastName)
@Html.EditorFor(m=>m.UserName)
@if(Model.Id ==0 )
{
// only in the add case you need to get the password value
@Html.EditorFor(m=>m.Password)
}
}
希望对你有帮助
关于c# - 一对一 Entity Framework 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39604491/