c# - 如何遍历 MultiSelectList 发布的值并将每个值插入 ASP.Net MVC 5 中的新数据库行?
问题描述
我已经访问了我能找到的所有搜索结果,但我被困住了。
我正在使用 ASP.Net MVC 5 开发“DVD 商店”网站,但在将 MultiSelectList 值插入数据库时遇到了一些困难。数据库结构有一个多对多表,其中存储电影 ID、流派 ID 和主键。还有一个电影表,其中包含电影标题、成本、图像路径、导演、评级等字段。
我的插入逻辑适用于将数据放入电影表中,但我的创建视图中有一个多选列表,该列表是从数据库中的电影类型列表中填充的。当我选择一个列表项时,ID 插入到 moviegenre 表中就好了。当我选择多个时,只插入一个 ID。我想为每个选择插入一个新行,其中包含电影 ID 和流派 ID(即,如果选择了 3 个流派,则创建 3 个具有相同电影 ID 但每行流派 ID 不同的新行)。
如何遍历发布的 MultiSelectList 数据并为每个值插入一个新行?
这是我视图中的代码:
@Html.ListBoxFor(r => r.CMovie.GenreId, new MultiSelectList(Model.CGenreList, "Id", "Description"), new { @class = "form-control" })
我的控制器:
[HttpPost]
public ActionResult Create(MovieGenresDirectorsRatings mgdr) // The ViewModel
{
try
{
mgdr.CMovie.Insert();
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
return View(mgdr);
}
}
视图模型:
public class MovieGenresDirectorsRatings
{
public IEnumerable<int> GenreId { get; set; }
public CGenreList CGenreList { get; set; }
public CDirectorList CDirectorList{ get; set; }
public CFormatList CFormatList { get; set; }
public CRatingList CRatingList { get; set; }
public CGenre CGenre { get; set; }
public CMovie CMovie { get; set; }
}
我在模型中的插入逻辑:
public void Insert()
{
using (myEntities dc = new myEntities())
{
try
{
tblMovie movie = new tblMovie();
// Add movie to tblMovie
movie.Id = 1;
if (dc.tblMovies.Any())
movie.Id = dc.tblMovies.Max(p => p.Id) + 1;
this.Id = movie.Id;
movie.Title = this.Title;
movie.Description = this.Description;
movie.ImagePath = this.ImagePath;
movie.Cost = this.Cost;
movie.RatingId = this.RatingId;
movie.FormatId = this.FormatId;
movie.DirectorId = this.DirectorId;
try
{
tblMovieGenre genre = new tblMovieGenre();
genre.Id = 1;
if (dc.tblMovieGenres.Any())
genre.Id = dc.tblMovieGenres.Max(p => p.Id) + 1;
// THIS IS THE PART that I'm struggling with.
// I think the data is there, I'm just not sure how to access it
foreach (var GenreId in GenreId) // This line is probably wrong, but I'm not sure how to access the data
{
genre.GenreId = this.GenreId.FirstOrDefault();
genre.MovieId = movie.Id;
dc.tblMovieGenres.Add(genre);
}
}
catch (Exception ex)
{
throw ex;
}
dc.tblMovies.Add(movie);
// Commit changes
dc.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
}
}
我已经尝试过 foreach 循环和 for 循环,但我无法让它工作。我究竟做错了什么?
编辑#1:进行一些更改后,这是我(当前和非工作)在 CMovie 类中的完整插入逻辑。当我只从 MultiSelectList 中选择一种“类型”时,它可以正常工作并正确插入到两个表中。但是,当我从 MultiSelectList 中选择两个或多个“流派”时,我收到“值不能为空,参数名称:项目”错误。
public void Insert()
{
using (dbEntities2 oDc = new dbEntities2())
{
try
{
tblMovie movie = new tblMovie();
// Add movie to tblMovie
movie.Id = 1;
if (oDc.tblMovies.Any()) // If table is not empty
movie.Id = oDc.tblMovies.Max(p => p.Id) + 1;
this.Id = movie.Id;
movie.Title = this.Title;
movie.Description = this.Description;
movie.ImagePath = this.ImagePath;
movie.Cost = this.Cost;
movie.RatingId = this.RatingId;
movie.FormatId = this.FormatId;
movie.DirectorId = this.DirectorId;
try
{
foreach (var GenreId in GenreIds)
{
tblMovieGenre genre = new tblMovieGenre();
genre.Id = 1;
if (oDc.tblMovieGenres.Any())
{
genre.Id = oDc.tblMovieGenres.Max(p => p.Id) + 1; // genre.Id is set to the highest id in the table, +1
}
genre.Id = this.Id;
genre.GenreId = GenreId;
genre.MovieId = movie.Id;
oDc.tblMovieGenres.Add(genre);
}
}
catch (Exception ex)
{
throw ex;
}
oDc.tblMovies.Add(movie);
// Commit changes
oDc.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
}
}
}`
编辑2:我找到了解决问题的方法。希望这可以帮助其他有同样问题的人。我将创建更改为使用下拉列表而不是多选列表,并修改了编辑方法以允许更新多种流派。
在CMovie
模型内部,我创建了两个新方法,AddGenre
并且DeleteGenre
. 在控制器中,我添加了四个新IEnumerable<int>
变量:oldGenreIds、newGenreIds、adds 和 deletes。
然后我从IEnumerable
删除列表中添加并添加:
IEnumerable<int> deletes = oldGenreIds.Except(newGenreIds);
IEnumerable<int> adds = newGenreIds.Except(oldGenreIds);
deletes.ToList().Foreach(a => mgdr.CMovie.DeleteGenre(id, a));
adds.ToList().Foreach(a => mgdr.CMovie.AddGenre(id, a));
然后调用 update 方法,设置更改的值(包括电影标题、描述、图像路径等):
mgdr.CMovie.Update();
通过将 ForEach 逻辑移动到控制器中,我能够AddGenre
多次调用该方法——当直接在方法内部调用它时,我无法做到这一点Insert
。
解决方案
这是问题(实际上是一个忽略):
tblMovieGenre genre = new tblMovieGenre();
// code...
foreach (var GenreId in GenreId)
{
genre.GenreId = this.GenreId.FirstOrDefault();
// code
dc.tblMovieGenres.Add(genre);
}
所以在上面的代码中你创建了一个tblMovieGenre
,然后在你的循环中你tblMovieGenres
一遍又一遍地添加相同的实例。tblMovieGenres
所以基本上你在循环中添加一个带有最后一次迭代的值的值。
使固定
要解决此问题,请在循环内移动实例化:
foreach (var GenreId in GenreId)
{
tblMovieGenre genre = new tblMovieGenre();
// code...
dc.tblMovieGenres.Add(genre);
}
其他建议
1
.NET 不鼓励使用匈牙利符号,因此为数据库表添加前缀tbl
不仅是符号问题,而且会使代码更难阅读,尤其是在使用 ORM 时。因此,如果您tbl
从表名中删除,您的代码将是:
MovieGenere
而不是tblMovieGenre
.
2
另外,如果我查看一行代码并且可以确定对象的类型,我总是使用它var
。像这样:
tblMovieGenre genre = new tblMovieGenre();
var genre = new tblMovieGenre();
这是个人喜好(少打字)。
但是,如果我无法通过读取单行来确定类型,那么我不使用var
:
tblMovieGenre genre = GetMovie();
3
如果你让你的表主键列identity
从 1 开始,那么你将不需要这样的代码:
movie.Id = 1;
if (dc.tblMovies.Any())
movie.Id = dc.tblMovies.Max(p => p.Id) + 1;
每当您在代码中创建新对象时,它的 ID 将为 0,当您将其添加到数据库时,EF 会将其视为新记录并为其生成新标识。这将管理 ID 的责任从您手中移开,这意味着更少的编码。
推荐阅读
- c# - 如果我已经将正则表达式作为 c# 属性的数据属性,我是否需要 stringlength
- javascript - javascript延迟后获取网站内容
- jquery - jQuery / 正则表达式模式:只允许数字一个逗号
- gradle - Gradle 项目的 Runner 类中无法解析导入黄瓜
- ios - Swift TapGestureRecognizer 和 UIButton
- android-gradle-plugin - Jacoco 0.8.2 和 Android Gradle 插件 3.2.0 测试覆盖率
- c++ - 是否可以重载“评估运算符”?
- javascript - 我如何知道我的 http 请求的结果是否完整且完整?
- macos - 这是什么操作系统
- ios - 无法将具有标识符的单元格出列,但仅在点击搜索时