簡體   English   中英

實體框架6多對多插入更新

[英]Entity framework 6 many to many insert update

我正在使用asp.net mvc,ef6開發問題/答案軟件。 我要解決的問題之一是插入/更新許多項目。 例如,如果用戶問一個問題並為其添加標簽,他們可以選擇現有標簽或創建新標簽。

我精簡的問題課是

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;
}

嘗試使用Include方法,讓EF為您管理關系。

 public void AddOrRemoveTags(IList<string> tags, Question question) { var dbQuestion = _context.Questions.Include(a => a.Tags).SingleOrDefault(a => a.QuestionId == question.QuestionId); 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(); } } 

對於新記錄:

 public void AddTags(IList<string> tags, Question question) { 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 }); } } } 

然后,您將需要在更高級別將Question對象添加到上下文中。 這應該添加所有相關參考,並且只需要花一小步就可以獲取您關心的標簽。 重要的一點是,您不會以這種方式從數據庫中提取整個標簽集。

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

將完整的標簽傳遞到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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM