我无法理解我是否正确地做到了这一点。我有3个相互依赖的实体。我正在尝试向这些实体添加新对象,然后调用保存更改,最终将相应的记录添加到符合FK约束的表中。
我收到错误:
无法定义两个对象之间的关系,因为它们附加到不同的ObjectContext对象。
在我的代码中,我正在使用linq解析一些XML,同时将新对象添加到上下文中。在我的服务层中,我有以下方法来处理传入数据。
public void ProcessSurvey(int surveyContentId, int caseNo, string surveyTitle, string reportVersion, string reportXml)
{
// get surveyid
var surveyContent = _surveyContentRepository.GetSurveyContent(surveyContentId);
// create response obj
var surveyResponse = new SurveyResponse()
{
SurveyId = surveyContent.SurveyId,
CaseNo = caseNo,
SurveyTitle = surveyTitle,
ReportVersion = reportVersion,
Created = DateTime.Now,
ResponseXML = reportXml
};
// add response obj to context?
_surveyResponseRepository.Add(surveyResponse);
// get the questions elements from the xml data
var questions = SurveyResponseHelper.GetResponseQuestions(reportXml);
// iterate over questions
foreach (XElement question in questions)
{
SurveyQuestion thisSurveyQuestion = SurveyResponseHelper.ProcSurveyQuestion(question, surveyContentId);
// add question?
_surveyQuestionRepository.Add(thisSurveyQuestion);
// get question answer
SurveyAnswer thisSurveyAnswer = SurveyResponseHelper.GetAnswer(question);
//update the answer with the question and response obj to satisfy the FK reference
thisSurveyAnswer.SurveyQuestion = thisSurveyQuestion;
thisSurveyAnswer.SurveyResponse = surveyResponse; // This is where it breaks ERRROR: The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects
_surveyAnswerRepository.Add(thisSurveyAnswer);
}
//commit
_surveyAnswerRepository.Save();
}
我的存储库看起来像这样..
public interface ISurveyAnswerRepository
{
void Add(SurveyAnswer surveyAnswer);
void Save();
}
public class SurveyAnswerRepository : Repository, ISurveyAnswerRepository
{
//private DiversionProgramsEntities _db;
public SurveyAnswerRepository()
{
//_db = new DiversionProgramsEntities();
}
public void Add(SurveyAnswer surveyAnswer)
{
this.DataContext.SurveyAnswers.AddObject(surveyAnswer);
}
public void Save()
{
this.DataContext.SaveChanges();
}
我的基础资料库
public class Repository
{
private DiversionProgramsEntities _dataContext;
public DiversionProgramsEntities DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.CreateContext()); }
}
}
和静态类/方法来创建上下文
public static class DatabaseFactory
{
public static DiversionProgramsEntities CreateContext()
{
return new DiversionProgramsEntities();
}
}
这是我的帮手代码..
public class SurveyResponseHelper
{
public static IEnumerable<XElement> GetResponseQuestions(string xmlResponseData)
{
XElement xmlData = XElement.Parse(xmlResponseData);
var questions = from n in xmlData.Descendants()
where n.Parent.Name.LocalName == "questions"
select n;
return questions;
}
public static SurveyQuestion ProcSurveyQuestion(XElement question, int surveyContentId)
{
// get the question type
var questionType = question.Name.LocalName;
// get question element text. This is the actual question text
var questionText = question.Elements().Where(e => e.Name.LocalName == "direction").SingleOrDefault().Value;
// check to see if this question exists in the data table, if it does then we will use the questionid from that which will get used to tie the SurveyAnswer to this question.
// if question does not already exist then a new one will be created
SurveyQuestionRepository surveyQuestionRepository = new SurveyQuestionRepository();
SurveyQuestion surveyQuestion;
surveyQuestion = surveyQuestionRepository.GetSurveyQuestion(surveyContentId, questionType, questionText);
if (surveyQuestion == null)
{
surveyQuestion = new SurveyQuestion()
{
QuestionText = questionText,
QuestionType = questionType,
SurveyContentId = surveyContentId
};
}
return surveyQuestion;
}
public static SurveyAnswer GetAnswer(XElement question)
{
// get the answer index value
var answers = question.Elements().Where(e => e.Name.LocalName == "answers").SingleOrDefault();
int userAnswerIndex = Int32.Parse(answers.Attribute("userAnswerIndex").Value);
// move the answers to an array so we can use the index to get the correct answer
XElement[] answersArray = answers.Elements().ToArray();
SurveyAnswer answer = new SurveyAnswer()
{
AnswerText = answersArray[userAnswerIndex].Value
};
return answer;
}
}
答案 0 :(得分:1)
看起来错误正在完美地描述正在发生的事情。在以下行中:
var questions = SurveyResponseHelper.GetResponseQuestions(reportXml);
你从另一个班级得到一个问题。该类可能会创建自己的对象上下文。
如果问题来自不同的对象上下文,则无法将问题附加到答案中。
要解决此问题,最简单的方法是为datacontext的方法GetResponseQuestions添加一个参数,这样您的其他方法就可以使用存储库datacontext来获取问题。
此外,各种IoC方法可以简化这一过程。
答案 1 :(得分:1)
_surveyContentRepository
来自哪里?如果它是静态的,我可以看到一个场景,其中一个SurveyContent
对象附加到一个DiversionProgramsEntities
,并且您的ProcSurveyQuestion()
方法找到并返回现有的SurveyQuestion
,附加到其他DiversionProgramsEntities
。
除此之外,我认为我可以给你的一般指针是使用对象本身而不是对象ID分配对象,所以代替:
var surveyResponse = new SurveyResponse { SurveyId = surveyContent.SurveyId }
...使用:
var surveyResponse = new SurveyResponse { Survey = surveyContent }
这会自动将新的SurveyResponse
对象添加到SurveyContent
对象所属的同一对象上下文中,这意味着您不必手动向存储库添加任何内容。您可以像这样组装整个对象图,然后在用于检索第一个对象的存储库中调用Save()
来保存整个对象。
答案 2 :(得分:0)
正如@TimHoolihan所述,问题在于您没有使用相同的数据上下文来访问调查回答和调查问题,实际上我认为问题在ProcSurveyQuestion方法的下面一行排列。
SurveyQuestionRepository surveyQuestionRepository = new SurveyQuestionRepository();
我看到你在DiversionProgramsEntities类中有一个单独的DataContext,但我无法从你的代码中推断出SurveyQuestionRepository和SurveryResponseRepositories是否也在使用相同的上下文。基于你得到的错误,我猜他们正在使用单独的上下文,所以再次@TimHoolihan建议,你需要修改你的代码以使用相同的上下文。
您还应该查看UnitOfWork模式,因为这是您要在此处尝试完成的模式,但是您没有共同的上下文来跟踪所有更改。