I have an entity "Question" that are used by both entities "QuestionSet" and "Survey". The logic is, create a set of questions, but when adding questions to a survey, create a clone so that editing question in a questionset will not change the question in the survey. However since there is explicit update functionality the clone (in survey) needs to know it's origin (question in questionset).
I solved this by added a
public virtual Question CreatedFrom { get; set; }
in Question. However when I now do as follows in my controller
oldQ = _questionRepository.GetById(qTransfer.Id);
q = new Question(oldQ);
q.CreatedFrom = oldQ;
q.Id = 0;
where the copy constructor of Q makes a complete copy of the question values (creating the clone).
And finally this in my repo
if (item.Id == 0)
{
Add(item); //this calls Add on dbset
}
ActiveContext.SaveChanges();
I get this error: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
If I comment away q.CreatedFrom = oldQ; then i no longer get the error.
What I want is simply to reference the questions parent when i create a clone. I still want the original question to operate independently. I could of course simply replace CreatedFrom with CreatedFromId, but i thought it would be nice with a direct reference.
Update
Here is my cloning code. While cloning I copy the reference for CreatedFrom however that should be null in the object being cloned.
public Question(Question q)
{
Id = q.Id;
Description = q.Description;
CreatedFrom = q.CreatedFrom;
Type = q.Type;
AddedTime = q.AddedTime;
DeletedTime = q.DeletedTime;
SortIndex = q.SortIndex;
IsPageBreak = q.IsPageBreak;
List<QuestionAlternative> list = new List<QuestionAlternative>();
QuestionAlternative alternative;
foreach (var alt in q.Alternatives)
{
alternative = new QuestionAlternative(alt);
alternative.Id = 0;
list.Add(alternative);
}
Alternatives = list;
}
The QuestionAlternative in turn has a copy constructor as so:
public QuestionAlternative(QuestionAlternative qa)
{
Id = qa.Id;
Text = qa.Text;
HasTextAnswer = qa.HasTextAnswer;
}