![](/img/trans.png)
[英]ASP.NET MVC 3.0 - Issue posting MultiSelectList values to database
[英]How to loop through MultiSelectList posted values and insert each into a new database row in 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);
}
}
ViewModel:
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類中我(當前的和無效的)完整的Insert邏輯。 當我從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:我找到了解決問題的方法。 希望這可以幫助其他遇到相同問題的人。 我將創建更改為使用下拉列表而不是多重選擇列表,並修改了edit方法以允許更新多個流派。
在CMovie
模型內部,我創建了兩個新方法, AddGenre
和DeleteGenre
。 在控制器中,我添加了四個新的IEnumberable<int>
變量:oldGenreIds,newGenreIds,添加和刪除。
然后,我從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
方法中調用它時,我無法執行此操作。
您的post方法應該接受數組,而不是單個對象。
[HttpPost]
public ActionResult Create(MovieGenresDirectorsRatings[] mgdr) // The ViewModel
{
foreach(var genr in mgdr){
try
{
genr.CMovie.Insert(); //inserting each object received from view.
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
return View(mgdr);
}
}
}
這個想法是從視圖中接收所有對象。 即使您的視圖正在發布多選列表中的所有項目,您也需要在控制器中使用類似數組的結構來從視圖中獲取數據。 將數據放入控制器后,就可以循環遍歷所有這些數據,並一一插入。
這里是問題(實際上是一個忽略):
tblMovieGenre genre = new tblMovieGenre();
// code...
foreach (var GenreId in GenreId)
{
genre.GenreId = this.GenreId.FirstOrDefault();
// code
dc.tblMovieGenres.Add(genre);
}
因此,請參見上面的代碼,創建一個tblMovieGenre
,然后在循環中不斷tblMovieGenres
添加相同的tblMovieGenres
實例。 因此,從本質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的責任,這意味着更少的編碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.