這個想法很簡單。我有一個標籤列表。當我創建一個問題時,我想添加一些標籤。多對多的關係 - 我做對了嗎?
型號:
public class QuestionModel
{
public int Id { get; set; }
public String Content { get; set; }
public ICollection<TagModeltoQuestionModel> Tags { get; set; }
[NotMapped]
public ICollection<TagModel> AssignedTags { get { return Tags.Select(x => x.Tag).ToList(); } }
public int UserId { get; set; }
}
public class QuestionViewModel // helper - not in database
{
public QuestionModel Model { get; set; }
public ICollection<TagModel> Tags { get; set; }
}
public class TagModel
{
public int Id { get; set; }
public String Name { get; set; }
public ICollection<TagModeltoQuestionModel> Questions { get; set; }
[NotMapped]
public bool Assigned { get; set; }
[NotMapped]
public ICollection<QuestionModel> AssignedQuestions { get { return Questions.Select(x => x.Question).ToList(); } }
}
public class TagModeltoQuestionModel // many to many
{
[Key, Column(Order = 0)]
public int TagId { get; set; }
[Key, Column(Order = 1)]
public int QuestionId { get; set; }
public virtual QuestionModel Question { get; set; }
public virtual TagModel Tag { get; set; }
}
控制器:
[HttpPost]
public ActionResult Edit(QuestionViewModel questionViewModel)
{
if (ModelState.IsValid)
{
_repo.Update(questionViewModel.Model, questionViewModel.Tags); // see repo code below
return RedirectToAction("Index");
}
return View(questionViewModel.Model);
}
回購:
public void Update(QuestionModel entity, ICollection<TagModel> tags)
{
AssignTags(entity, tags);
Db.Attach(entity);
Db.SaveChanges();
}
private void AssignTags(QuestionModel entity, ICollection<TagModel> tags)
{
tags = tags.Where(x => x.Assigned).ToArray(); // remove unassigned comming form View --> Controller
var linkedTags =
Db.TagsToQuestions.Where(x => x.QuestionId == entity.Id);
var linkedTagsIds = linkedTags.Select(x => x.TagId);
var selectedTagsIds = tags.Select(x => x.Id);
var oldTags = linkedTags.Where(x => !selectedTagsIds.Contains(x.TagId));
var newTags = tags.Where(x => !linkedTagsIds.Contains(x.Id)).Select(x=> new TagModeltoQuestionModel{QuestionId=entity.Id,TagId=x.Id});
foreach (var t in oldTags)
Db.Delete(t);
foreach (var t in newTags)
Db.Add(t);
Db.SaveChanges();
}
這工作得很好,雖然我不知道這是去(正道實際上我自己實現了整個多對多邏輯)。有沒有更聰明的方法讓EF爲我做這份工作?我通過一堆教程挖掘,但沒有一個爲我工作。
此外,我覺得AssignTags方法可以寫得更好,所以任何意見也表示讚賞。
編輯
根據haim770的回答我的簡化模型,他建議的方式。
我的控制器現在看起來像這樣:
public void Update(QuestionModel entity, ICollection<TagModel> tags)
{
Db.Attach(entity);
//these lines give the same result
//var ids = tags.Select(y => y.Id).ToArray();
//entity.Tags = Db.Tags.Where(x => ids.Contains(x.Id)).ToArray();
tags.ForEach(x => Db.Attach(x));
entity.Tags = tags;
Db.SaveChanges();
}
的SaveChanges導致錯誤:
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.
inner:
{"A duplicate value cannot be inserted into a unique index. [ Table name = TagModelQuestionModels,Constraint name = PK_TagModelQuestionModels ]
那麼如何正確地執行呢?
您的問題似乎更適合http://codereview.stackexchange.com StackOverflow是一個編程相關的問答網站,你應該只問問題,你可能會遇到問題遇到一段特定的代碼。 – 2013-03-17 12:18:33
@DarinDimitrov部分你是對的。我可能會問'如何實現一個多對多的關係',因爲這是我的真正意義,但是我包含了更具體的代碼。 – gisek 2013-03-17 12:23:42
好的,那麼你遇到這個代碼有什麼特別的問題?什麼不起作用?你收到了什麼錯誤信息? StackOverflow是一個問答網站,用戶可以詢問關於他們遇到問題的特定代碼的具體問題。那麼你呢?你遇到了什麼問題,這些代碼有什麼不工作?如果您無法回答這些問題,只是要求進行代碼審查或是否有更好的方法來實現某些內容,那麼,正如我在第一條評論中所述,您的問題更適合http://codereview.stackexchange。com/ – 2013-03-17 12:24:19