gpt4 book ai didi

asp.net-mvc - 在 MVC 创建 View 上保存多对多关系数据

转载 作者:行者123 更新时间:2023-12-01 17:35:53 24 4
gpt4 key购买 nike

我在保存创建 View 的结果时遇到了多对多关系的一些问题。

我想为新用户配置文件创建一个创建页面,该页面有一个 list ,可以让他们选择类(class)(多对多关系)。我的 View 从 Courses 数据库中获取记录,并通过复选框显示所有记录。

用户发布数据后,我想更新我的 userprofile 模型以及 courses 多对多关系。这就是我缺少的代码!

我是 MVC 新手,我一直在研究,但还无法做到。

我正在遵循这个例子: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application

这是模型:

public class UserProfile
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Courses> usercourses { get; set; }
}

public class Courses
{
public int CourseID { get; set; }
public string CourseDescripcion { get; set; }
public virtual ICollection<UserProfile> UserProfiles { get; set; }
}

public class UserProfileDBContext : DbContext
{
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Courses> usrCourses{ get; set; }
}

我还添加了一个 ViewModel:

namespace Mysolution.ViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string CourseDescription { get; set; }
public bool Assigned { get; set; }
}
}

这是填充类(class)复选框的create Controller :

public ActionResult Create()
{
PopulateCoursesData();
return View();
}

private void PopulateCoursesData()
{
var CoursesData = db.usrCourses;
var viewModel = new List<AssignedCourseData>();
foreach (var item in CoursesData)
{
viewModel.Add(new AssignedCourseData {
CourseID = item.CourseID,
CourseDescription = item.CourseDescription,
Assigned = false });
}
ViewBag.CoursePopulate = viewModel;
}

这是 View

@{
int cnt = 0;
List<MySolution.ViewModels.AssignedCourseData> courses = ViewBag.CoursePopulate;

foreach (var course in courses)
{
<input type="checkbox" name="selectedCourse" value="@course.CourseID" />
@course.CourseDescription
}
}

这是获取数据的 Controller (以及我想要保存数据的位置)。它作为复选框的参数 string[] selectedCourse 获取:

[HttpPost]
public ActionResult Create(UserProfile userprofile, string[] selectedCourse)
{
if (ModelState.IsValid)
{
db.UserProfiles.Add(userprofile);

//TO DO: Save data from many to many (this is what I can't do!)

db.SaveChanges();
}

return View(userprofile);
}

最佳答案

编辑:我已用代码将其写在 3 篇博文中

  • part 1设置解决方案并创建新用户
  • part 2添加类(class)并将其与用户个人资料一起保存
  • part 3允许编辑和删除用户及其类(class)

Github来源: https://github.com/cbruen1/mvc4-many-to-many

<小时/>

我认为您在某些命名方面有点偏离了惯例,因此我在我认为合适的地方进行了更改。在我看来,将类(class)作为用户配置文件的一部分发布回来的最佳方法是让它们由编辑器模板呈现,我将在后面进一步解释。

以下是我实现这一切的方法:

(感谢@Slauma 指出保存新类(class)时的错误)。

  • 在您的模型中,您的“类(class)”类是单个实体,通常被命名为“类(class)”,并且类“类(class)”的集合将被命名为“类(class)”。
  • 不要使用 ViewBag 中的AssignedCourseData,而是使用 View 模型
  • 在创建新用户时实现这一点 - 即为包含分配的类(class)数据 View 模型的用户配置文件创建一个标准的创建 View ,该 View 模型将与 UserProfileViewModel 一起回发。

从数据库开始,保留 UserProfile 集合不变,并将类(class)集合命名为 Courses:

public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Course> Courses { get; set; }

在 DbContext 类中重写 OnModelCreating 方法。这是映射 UserProfile 和 Course 之间多对多关系的方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<UserProfile>()
.HasMany(up => up.Courses)
.WithMany(course => course.UserProfiles)
.Map(mc =>
{
mc.ToTable("T_UserProfile_Course");
mc.MapLeftKey("UserProfileID");
mc.MapRightKey("CourseID");
}
);

base.OnModelCreating(modelBuilder);
}

我还会在同一命名空间中添加一个模拟初始化程序类,这将为您提供一些入门类(class),并且意味着您不必在每次模型更改时手动添加它们:

public class MockInitializer : DropCreateDatabaseAlways<MVC4PartialViewsContext>
{
protected override void Seed(MVC4PartialViewsContext context)
{
base.Seed(context);

var course1 = new Course { CourseID = 1, CourseDescripcion = "Bird Watching" };
var course2 = new Course { CourseID = 2, CourseDescripcion = "Basket weaving for beginners" };
var course3 = new Course { CourseID = 3, CourseDescripcion = "Photography 101" };

context.Courses.Add(course1);
context.Courses.Add(course2);
context.Courses.Add(course3);
}
}

将此行添加到 Application_Start() Global.asax 以启动它:

Database.SetInitializer(new MockInitializer());

所以这是模型:

public class UserProfile
{
public UserProfile()
{
Courses = new List<Course>();
}
public int UserProfileID { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
public int CourseID { get; set; }
public string CourseDescripcion { get; set; }
public virtual ICollection<UserProfile> UserProfiles { get; set; }
}

现在在您的 Controller 中创建 2 个新操作结果以创建新的用户配置文件:

public ActionResult CreateUserProfile()
{
var userProfileViewModel = new UserProfileViewModel { Courses = PopulateCourseData() };

return View(userProfileViewModel);
}

[HttpPost]
public ActionResult CreateUserProfile(UserProfileViewModel userProfileViewModel)
{
if (ModelState.IsValid)
{
var userProfile = new UserProfile { Name = userProfileViewModel.Name };

AddOrUpdateCourses(userProfile, userProfileViewModel.Courses);
db.UserProfiles.Add(userProfile);
db.SaveChanges();

return RedirectToAction("Index");
}

return View(userProfileViewModel);
}

这是您的 PopulateCourseData,与您的方式类似,只是不放入 ViewBag 中 - 它现在是 UserProfileViewModel 上的一个属性:

private ICollection<AssignedCourseData> PopulateCourseData()
{
var courses = db.Courses;
var assignedCourses = new List<AssignedCourseData>();

foreach (var item in courses)
{
assignedCourses.Add(new AssignedCourseData
{
CourseID = item.CourseID,
CourseDescription = item.CourseDescripcion,
Assigned = false
});
}

return assignedCourses;
}

创建编辑器模板 - 在您的 Views\Shared 文件夹中创建一个名为 EditorTemplates 的新文件夹(如果您还没有)。添加一个名为“AssignedCourseData”的新部分 View 并粘贴下面的代码。这是正确渲染和命名所有复选框的神奇之处 - 您不需要 for every 循环,因为编辑器模板将创建集合中传递的所有项目:

@model AssignedCourseData
@using MySolution.ViewModels

<fieldset>
@Html.HiddenFor(model => model.CourseID)
@Html.CheckBoxFor(model => model.Assigned)
@Html.DisplayFor(model => model.CourseDescription)
</fieldset>

在 View 模型文件夹中创建一个用户个人资料 View 模型 - 其中包含一个AssignedCourseData 对象的集合:

public class UserProfileViewModel
{
public int UserProfileID { get; set; }
public string Name { get; set; }
public virtual ICollection<AssignedCourseData> Courses { get; set; }
}

添加一个名为 CreateUserprofile.cshtml 的新 View 来创建用户配置文件 - 您可以右键单击已添加的 CreateUserProfile Controller 方法并选择“添加 View ”:

@model UserProfileViewModel
@using MySolution.ViewModels

@using (Html.BeginForm("CreateUserProfile", "Course", FormMethod.Post))
{
@Html.ValidationSummary(true)

<fieldset>

@Html.DisplayFor(model => model.Name)
@Html.EditorFor(model => model.Name)

// Render the check boxes using the Editor Template
@Html.EditorFor(x => x.Courses)

</fieldset>

<p>
<input type="submit" value="Create" />
</p>
}

这将正确呈现字段名称,以便在表单回发到 Controller 时它们成为用户个人资料 View 模型的一部分。这些字段将被命名为:

<fieldset>
<input data-val="true" data-val-number="The field CourseID must be a number." data-val-required="The CourseID field is required." id="Courses_0__CourseID" name="Courses[0].CourseID" type="hidden" value="1" />
<input data-val="true" data-val-required="The Assigned field is required." id="Courses_0__Assigned" name="Courses[0].Assigned" type="checkbox" value="true" /><input name="Courses[0].Assigned" type="hidden" value="false" />
Bird Watching
</fieldset>

其他字段的命名方式类似,但分别使用 1 和 2 进行索引。最后,介绍了如何在表单回发时将类(class)保存到新的用户配置文件中。将此方法添加到您的 Controller - 当表单回发时,从 CreateUserProfile 操作结果调用此方法:

private void AddOrUpdateCourses(UserProfile userProfile, IEnumerable<AssignedCourseData> assignedCourses)
{
foreach (var assignedCourse in assignedCourses)
{
if (assignedCourse.Assigned)
{
var course = new Course { CourseID = assignedCourse.CourseID };
db.Courses.Attach(course);
userProfile.Courses.Add(course);
}
}
}

一旦类(class)成为用户配置文件的一部分,EF 就会处理关联。它将为选定的每门类(class)添加一条记录到 OnModelCreating 中创建的 T_UserProfile_Course 表中。以下是 CreateUserProfile 操作结果方法,显示发回的类(class):

Courses check boxes posted back to the controller

我选择了 2 门类(class),您可以看到这些类(class)已添加到新的用户个人资料对象中:

Courses added to new userprofile object

关于asp.net-mvc - 在 MVC 创建 View 上保存多对多关系数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11531769/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com