将未更改的项添加到已添加项的对象图中

one*_*ill 6 entity-framework

我有一个名为Option的域对象.它是更大的测验架构的一部分.该表中的前两个主键(Id)与Text列的值"true"和"false"相关联.但在那之后,该表中的项目对于该问题的范围没有任何影响.这两行"真"和"假"的重要性在于它们将被重复使用多次.

另请注意,Option表是一个标识(自动增量)表.我在OptionMap文件中有以下内容:

this.HasKey(t => t.Id);
this.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Run Code Online (Sandbox Code Playgroud)

显然,每次在测验中添加带有true和false选项的新问题时,我不想继续向该表添加true和false.

在JavaScript中,在客户端,我编写了这样的代码,以便在创建新测验时,添加true和/或false作为问题的选项,然后将Id 1和2添加到发送到服务器的对象中(分别为真和假 - 召回前2行,如帖子顶部所述).当问题没有使用其中任何一个作为选项时,发送到服务器的选项的Id是未定义的.

在服务器上,在我的服务中,我编写了以下代码,它能够检测到作为选项添加了true或false,并尝试使用选项表中的现有存储值true/false(如果适用) :

foreach (var question in newQuestions)
{       
    _quizRepository.AddQuestion(question);
    var options = question.QuestionWithOptions.Select(q => q.Option).ToList();

    // This loop is an edge case. true and false will be very common answers. Rather than storing them over and over again,
    // this loop will re-use the already stored answers for true and false, which complies with the quiz schema.
    foreach (var option in options)
    {
        if (option.Text.Equals("true", StringComparison.OrdinalIgnoreCase) ||
            option.Text.Equals("false", StringComparison.OrdinalIgnoreCase))
        {
            var storedOption = _quizRepository.Context.Option.Single(o => o.Id == option.Id);
            foreach (var questionWithOption in question.QuestionWithOptions)
            {
                if (questionWithOption.Option.Id == storedOption.Id)
                {
                    questionWithOption.Option = storedOption;
                    _quizRepository.Context.Entry(questionWithOption.Option).State = EntityState.Unchanged;
                }
            }
        }                    
    }

    _quizRepository.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

我试图将状态设置为Unchanged和Modified,但每次调用SaveChanges时,它都会为true和false添加新行.如上所述,这正是我想要避免的.

任何有关如何使用现有的"真实"和"假"选项保存这些新问题的帮助将不胜感激.

编辑 - 添加域类

题:

public partial class Question
{
    public Question()
    {
        QuestionWithOptions = new List<QuestionWithOption>();
        QuizWithQuestions = new List<QuizWithQuestion>();
    }
    public int Id { get; set; }
    public string Text { get; set; }
    public int? idTimeLimit { get; set; }
    public QuestionType idType { get; set; }

    public virtual ICollection<QuestionWithOption> QuestionWithOptions { get; set; }
    public virtual ICollection<QuizWithQuestion> QuizWithQuestions { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

QuestionWithOption:

public partial class QuestionWithOption
{
    public int Id { get; set; }
    public int idQuestion { get; set; }
    public int idOption { get; set; }
    public bool CorrectAnswer { get; set; }
    public string Letter { get; set; }
    public virtual Option Option { get; set; }
    public virtual Question Question { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

选项:

public partial class Option
{
    public Option()
    {
        this.QuestionWithOptions = new List<QuestionWithOption>();
    }

    public int Id { get; set; }
    public string Text { get; set; }
    public virtual ICollection<QuestionWithOption> QuestionWithOptions { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

添加问题方法

这在以下两行代码之间切换(我正在尝试任何事情和所有事情)

    public void AddQuestion(Question question)
    {
        //((TTSWebinarsContext) db).Question.Attach(question);
        ((TTSWebinarsContext) db).Question.Add(question);
    }
Run Code Online (Sandbox Code Playgroud)

编辑 - 最终评论

让我加上这种情况多么荒谬.在同一操作中,它向Option表添加新选项(而不是使用现有选项1和2),插入QuestionWithOption表的值是正确的值,即1和2.因此,操作本身不是甚至声音.Option表中添加了多余的值,这些值甚至不是操作中的任何内容的FK.我开始了解NHibernate的粉丝了.

one*_*ill 0

终于弄清楚了缺少的一件事。工作代码如下:

foreach (var question in newQuestions)
{
    _quizRepository.AddQuestion(question);

    var options = question.QuestionWithOptions.Select(q => q.Option).ToList();

    // This loop is an edge case. true and false will be very common answers. Rather than storing them over and over again,
    // this loop will re-use the already stored answers for true and false, which complies with the quiz schema.

    var optionsToDelete = new List<Option>();

    foreach (var option in options)
    {
        if (option.Text.Equals("true", StringComparison.OrdinalIgnoreCase) ||
            option.Text.Equals("false", StringComparison.OrdinalIgnoreCase))
        {
            var storedOption = _quizRepository.Context.Option.Single(o => o.Id == option.Id);

            foreach (var questionWithOption in question.QuestionWithOptions)
            {
                if (questionWithOption.Option.Id == storedOption.Id)
                {
                    optionsToDelete.Add(option);
                    questionWithOption.idOption = storedOption.Id;
                }
            }
        }
    }

    _quizRepository.Context.Option.RemoveRange(optionsToDelete);
    _quizRepository.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

当我按预期分配 StoredOption 时,最初添加到对象图中的选项是悬空的。所以我必须在调用 SaveChanges 之前将其从上下文中删除。我创建了一个列表来在 foreach 循环期间收集这些选项,然后在调用 SaveChanges 上方的行上调用 RemoveRange。

又脏又乱,但是有用。现有选项现在用于“true”和“false”,而不是一遍又一遍地创建它们。