2014-09-29 86 views
0

我正在使用asp.net mvc,ef6處理問題/答案軟件。我試圖解決的問題之一是插入/更新許多項目。例如,如果用戶提出問題並添加標籤,他們可以選擇現有標籤或創建新標籤。實體框架6多對多插入更新

我剝離下來的問題類是

public class Question 
{ 
    private ICollection<Tag> _tags; 
    public long Id { get; set; } 
    public string Body { get; set; } 

    public virtual ICollection<Tag> Tags 
    { 
     get { return _tags ?? (_tags = new Collection<Tag>()); } 
     set { _tags = value; } 
    } 
} 

我的標籤類就像

public class Tag 
{ 
    private ICollection<Question> _questions; 

    public long Id { get; set; } 
    public string Text { get; set; } 

    public virtual ICollection<Question> Questions 
    { 
     get { return _questions?? (_questions=new Collection<Question>()); } 
     set { _questions = value; } 
    } 
} 

我的背景是像

public class MyDbContext 
     : DbContext 
{ 
    public virtual DbSet<Tag> Tags { get; set; } 
    public virtual DbSet<Question> Questions { get; set; } 
} 

當我需要保存的問題標籤我必須手動檢查用戶是否添加了標籤問題是否存在。如果它們不存在,我創建它們並保存上下文,然後返回標籤並將它們添加到問題中。我想知道是否有更好的方法在EF6中做這樣的事情?

我的示例代碼如下

public IEnumerable<Tag> CreateOrRetrieveTags(IList<string> tags) 
{ 
    List<string> availableTags = (from t in _context.Tags 
     where tags.Contains(t.Text) 
     select t.Text).ToList(); 
    var missingTags = tags.Except(availableTags, StringComparer.OrdinalIgnoreCase); 
    foreach (string missingTag in missingTags) 
    { 
     _context.Tags.Add(new Tag 
     { 
      Text = missingTag 
     }); 
    } 
    _context.SaveChanges(); 
    return from t in _context.Tags 
     where tags.Contains(t.Text) 
     select t; 
} 

回答

0

通完整的標籤爲CreateOrRetrieveTags方法,那麼你可以通過ID過濾器,以確定新的標籤:

public List<Tag> CreateOrRetrieveTags(List<Tag> tags) 
{ 
    var newTags = tags.Where(t => t.Id == 0); 
    foreach (string newTag in newTags) 
    { 
     _context.Tags.Add(newTag); 
    } 
    _context.SaveChanges(); 

    return from t in _context.Tags 
     where tags.Any(t.Text == t.Text) 
     select t; 
} 
+0

但是在那個階段我沒有完整的標籤。有點像Stackoverflow時,用戶添加標籤問題我只有標籤字符串/文本。 – 2014-09-29 18:48:03

+0

@QaiserIftikhar你不需要完整的標籤。如果是新標籤,你可以在javascript中創建一個標籤對象,默認爲零。 – 2014-09-29 18:49:47

+0

對不起,不知道你的意思。我從用戶那裏得到的是一個帶有特定字段的表單,例如問題主體,標題,標籤。我收到的標籤文本類似於wpf,c#,mvc,java。我用逗號分隔標籤文本,然後根據文本詢問我的上下文以查看數據庫中的標籤。在那個階段,我如何創建一個完整的標籤而不是首先檢索與用戶輸入的標籤匹配的標籤列表? – 2014-09-29 18:54:44

1

嘗試使用包括方法,讓EF管理你的關係。

public void AddOrRemoveTags(IList<string> tags, Question question) 
 
{ 
 
    var dbQuestion = _context.Questions.Include(a => a.Tags).SingleOrDefault(a => a.QuestionId == question.QuestionId); 
 
\t 
 
    if (dbQuestion != null) 
 
    { 
 
     var remainingTags = new List<string>(tags); 
 
     var tagsToRemove = dbQuestion.Tags.Where(t => !tags.Contains(t.Text, StringComparer.OrdinalIgnoreCase)).ToList(); 
 
     foreach (var tag in tagsToRemove) 
 
     { 
 
     dbQuestion.Tags.Remove(tag); 
 
     remainingTags.remove(tag.Text); 
 
     } 
 
     foreach(var remainingTag in remainingTags){ 
 
     dbQuestion.Tags.Add(new Tag(){ Text = remainingTag }); 
 
     } 
 
     _context.SaveChanges(); 
 
\t \t   
 
    } 
 
}

新記錄:

public void AddTags(IList<string> tags, Question question) 
 
{  \t 
 
    if (question != null) 
 
    { 
 
    var existingTags = _context.Tags.Where(t => tags.ToArray().Contains(t.Text)).ToList() 
 
    var remainingTags = new List<string>(tags); 
 
    foreach (var tag in existingTags) 
 
    { 
 
     question.Tags.Add(tag); 
 
     remainingTags.remove(tag.Text); 
 
    } 
 
    foreach(var remainingTag in remainingTags){ 
 
     question.Tags.Add(new Tag(){ Text = remainingTag }); 
 
    } 
 

 
    } 
 
}

然後你就需要在更高層次上你的問題對象添加到上下文。這應該添加所有相關的參考資料,並且只做一小段旅行即可獲取您關心的標籤。一個重要的部分是你不用這種方式從數據庫中提取整個標籤集。

注意:如果您關心區分大小寫,您可以.toLower()整個列表和.toLower()t.Text,這將轉換爲SQL。

+1

當我需要更新問題時,您的答案是有效的,但我試圖解決的第一個問題是用戶使用x個標籤添加了一個新問題。話雖如此,它仍然是我想要的太多代碼,可以用某種通用的方式來做。 – 2014-09-29 22:16:41

+0

我的編輯添加了對你有用的東西嗎? – Jarga 2014-09-29 23:18:23