我有两个类,歌曲和标签。这种关系是多对多的。我遇到的问题是,当用户添加新歌并检查他/她想要的标签时,我在控制器中调用db.SaveChanges(),它会添加重复的标签,而不是仅向连接表添加记录。我已经解决了这个问题,但这是一个黑客攻击。必须有更好的解决方案吗?
这是我的代码(为了清晰起见而缩略)。
曲:
public int Id { get; set; }
public List<Tag> Tags { get; set; }
public string SongTitle { get; set; }
标签:
public int Id { get; set; }
public string TagName { get; set; }
public bool Selected { get; set; }
public List<Song> Songs { get; set; }
控制器:
public ActionResult Create()
{
Song song = new Song();
song.Tags = utilities.TagNames(_db, User.Identity.Name);
return View(song);
}
[HttpPost]
public ActionResult Create(Song song)
{
//cycle thru the tags and grab ids of checked tags
int tagCount = song.Tags.Count;
List<int> tagIds = new List<int>();
for (int i = tagCount - 1; i > -1; i--)
{
Tag tag = song.Tags[i];
if (tag.Selected)
tagIds.Add(tag.Id);
}
song.Tags = null;
if (ModelState.IsValid)
{
_db.Songs.Add(song);
_db.SaveChanges();
int songId = song.Id;
string sql = "INSERT INTO [dbo].[TagSongs] (Tag_Id, Song_Id) VALUES ";
foreach(int tagid in tagIds)
{
sql += "(" + tagid + "," + songId + "),";
}
//remove the last comma
sql = sql.Substring(0, sql.Length - 1);
_db.Database.ExecuteSqlCommand(sql);
return RedirectToAction("Index");
}
SetCategoriesAndTags(song);
return View(song);
}
查看:
@for (int i = 0; i < Model.Tags.Count; i++)
{
Tag t = Model.Tags[i];
@Html.CheckBoxFor(m => m.Tags[i].Selected)
<label for="Tags_@i.ToString()__Selected">@t.TagName</label>
@Html.HiddenFor(m => m.Tags[i].Id)
@Html.HiddenFor(m => m.Tags[i].TagName)
}
答案 0 :(得分:0)
首先,不要对SQL查询使用字符串连接,否则会打开SQL注入攻击。这段代码可以满足您的需求。从控制器ActionMethod中调用它。
private void AddSongs(Song song, List<int> tagIds)
{
_db.Songs.Add(song);
foreach(var tagId in tagIds)
{
var tag = _db.Tags.SingleOrDefault(tagId);
if(tag != null) song.Tags.Add(tag);
}
_db.SaveChanges();
}