2016-09-20 163 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