2016-09-20 138 views
2

在我的数据模型(实体框架6.1.3,ASP.NET MVC 5,代码第一次与现有数据库中)有两个表,“”和“用户 “它们拥有一对一的关系。 “用户”表格有PKPersonID列依次是“Person”表的PK。我希望每当创建一个新的用户记录时,都会自动创建一个Person记录(第一个),然后将Person表中PersonID的值插入到新用户记录中。一比一实体框架的关系

这是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 

谢谢,galaf。

回答

2

我的回答你的数据库结构应该是这样的

  1. 用户:(是PersonID INT(PK,FK),名称为nvarchar(20))
  2. (PersonID int(PK,identity),...)

为上述DB结构通过一个错误,如果你试图救孤Person没有User,反之亦然转化为实体框架配置

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); 

} 

上述配置(1-1关系会)。

注意:我建议建立一个(1-0..1关系),因为逻辑上 User严格取决于人(弱实体),而 Person可以单独存在,而无需用户。 1配置:0..1 非常类似于上面的配置,唯一不同的是使 .HasOptional(p=>p.User)代替.HasRequired(p=>p.User)

现在,当您创建用户的实体,您的代码应该是这样的

var user = new User(){ 
    Name = "UserName", 
    Person = new Person(){ 
     FirstName="FirstName", 
     LastName ="LastName", 
     ... 
    } 
}; 

db.Users.Add(user); 
db.SaveChanges(); 

上述代码将强制在创建用户对象时创建person对象。

更新:对于你的情况

我建议你创建一个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的代码可以处理在一个动作中创建和编辑如下,只要两个视图相同,这将允许您编码较少。

[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); 
} 

您查看CreateOrEdit.cshtml应该是什么样子,我也不会只是为了使其简单

@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) 
     } 
} 

希望这将帮助你

+0

正如我在我的回答中所建议的,用户具有'PersonID'作为PK和FK,所以当你想提交你的数据时('Create' post action),你需要建立两个实体('User和Person'),所以在你的视图,你应该显示两个实体数据 – Monah

+0

我编辑了答案,为你的案例添加代码。 – Monah

+0

是的UserDTO是一个新的类,更好地使它在单独的文件,本文将帮助您更好地了解DTO的使用http://www.asp.net/web-api/overview/data/using-web -api-with-entity-framework/part-5 – Monah

-2

我记得前一阵子做这个。我认为你需要制作Person类抽象。并让用户从它继承。我认为EF应该自动处理加入两个表格。

下面是一个例子:

[Table("Person")] 
public abstract class Person 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
} 

[Table("User")] 
public class User : Person 
{ 
    public string Name { get; set; } 
} 

public class MyContext : DbContext 
{ 
    public DbSet<Person> People { get; set; } 
    public DbSet<User> Users { get; set; } 
} 

而且在我的配置增加了几个User就像这样:

internal sealed class Configuration : DbMigrationsConfiguration<MyContext> 
{ 
    public Configuration() 
    { 
     AutomaticMigrationsEnabled = true; 
    } 

    protected override void Seed(MyContext context) 
    { 
     context.Users.AddOrUpdate(
      p => p.Name, 
      new User {Name = "Test User #1"}, 
      new User {Name = "Test User #2"}, 
      new User {Name = "Test User #3"}); 
    } 
} 

及以下什么是数据库产生

The results

更多相关信息ava关于EF中的型号继承,可用here关于型号继承

+0

感谢mrstebo添加HTML代码和标签。任何细节? – galaf

+0

稍后我接到我的电脑后,我会编辑我的答案 – mrstebo

+0

只是对我的回答进行了更改,详细阐述了我的意思 – mrstebo