费用通过QuestionID和AnswerID外键链接到PropertySurvey中的AnsweredQuestion。 成本也可以通过UnitsQuestionID链接到同一PropertySurvey中的AnsweredQuestion,并再次通过ReplacementQuestionID链接。 以下是作为内部联接的查询 - 以避免@CraigStuntz regards as "messy"
的连接语法的方式编写var propertyCosts = from aq in answeredQuestions
from a in aq.Answers
from c in costs
where aq.QuestionID == c.QuestionID && a.ID == c.AnswerID
from uq in answeredQuestions
where uq.QuestionID == c.UnitsQuestionID
&& uq.PropertySurveyID == aq.PropertySurveyID
from rq in answeredQuestions
where rq.QuestionID == c.ReplacementQuestionID
&& rq.PropertySurveyID == aq.PropertySurveyID
select new PropertyCost(aq.Question.Text,
a.Text,
c.Amount,
uq.IntegerAnswer.GetValueOrDefault(1),
rq.IntegerAnswer.GetValueOrDefault(0));
是否可以在没有DefaultIfEmpty
内容的情况下使用左连接将其重写为UnitQuestion和ReplacementQuestion?
答案 0 :(得分:0)
为了跟随Craig Stuntz,您需要拥有您的逻辑可以遵循的关联。
因此,为了模拟你的许多人,你会得到一个中间表,它与问题和答案之间有1-Many关联。您可以在此处使用“成本”,并且无需任何费用即可实现零成本。
所以
问题(QuestionId)1 - > 1 .. *费用(QuestionId) 答案(AnswerId)1 - > 1 .. *费用(AnswerId) 问题(QuestionId)1 - > 0 .. *成本(UnitQuestionId) 问题(QuestionId)1 - > 0 .. *费用(ReplacementQuestionId)
然后在你的模型中创建关联
Question (Property = Costs) -- (Property = Question) Costs
Question (no mapping) -- (Property = UnitQuestion) Costs
Question (no mapping) -- (Property = ReplacementQuestion) Costs
Answer (Property = Costs) -- (Property = Answer) Costs
此查询应与查询的行为相匹配。
from aq in answeredQuestions
from c in aq.Costs
select new PropertyCost(aq.Question.Text,
c.Answer.Text,
c.Amount,
c.UnitQuestion == null ? 0 : c.UnitQuestion.IntegerAnswer
c.ReplacementQuestion == null ? 0 : c.ReplacementQuestion.IntegerAnswer
答案 1 :(得分:0)
//Make this problem less complicated to explain by abstracting the inner join
//that we always need.
//For efficiency this should probably be put back in line
var A = from aq in answeredQuestions
from a in aq.Answers
from c in costs
where aq.QuestionID == c.QuestionID && a.ID == c.AnswerID
select new
{
QuestionText = aq.Question.Text,
AnswerText = a.Text,
Amount = c.Amount,
PropertySurveyID = aq.PropertySurveyID,
PropertySurvey = aq.PropertySurvey,
UnitsQuestionID = c.UnitsQuestionID,
UnitsQuestion = c.UnitsQuestion
};
//This is how to do it using the explicit join keyword
var B = from a in A
join lj in answeredQuestions on
new {
a.PropertySurveyID,
UnitsQuestionID = a.UnitsQuestionID.GetValueOrDefault(0)
}
equals new {
lj.PropertySurveyID,
UnitsQuestionID = lj.QuestionID
}
into unitQuestions
from uq in unitQuestions.DefaultIfEmpty()
select new PropertyCost(a.QuestionText,
a.AnswerText,
a.Amount,
uq == null ? 1 : uq.IntegerAnswer.GetValueOrDefault(1));
//I thought this might do it but the filter on the navigational property
//means it's equivalent to an inner join
var C = from a in A
from uq in a.PropertySurvey
.AnsweredQuestions
.Where(x => x.QuestionID == a.UnitsQuestionID)
select new PropertyCost(a.QuestionText,
a.AnswerText,
a.Amount,
uq == null ? 1 : uq.IntegerAnswer.GetValueOrDefault(1));
//This is the solution
//Back to the basics described by @CraigStuntz
//Just that we have to navigate further to get to the Units value
//Is this less "messy" than a join? Not sure. Maybe if you can think in Linq...
var D = from a in A
select new PropertyCost
(
a.QuestionText,
a.AnswerText,
a.Amount,
a.PropertySurvey
.AnsweredQuestions
.Where(x => x.QuestionID == a.UnitsQuestionID)
.FirstOrDefault() == null
?
1
: a.PropertySurvey
.AnsweredQuestions
.Where(x => x.QuestionID == a.UnitsQuestionID)
.FirstOrDefault()
.IntegerAnswer.GetValueOrDefault(1)
);
//And here I have further refined it by putting the initial inner join back
//inline and using the let keyword define how to retrieve the unit question.
//This makes it much more readable:
var E = from aq in answeredQuestions
from a in aq.Answers
from c in costs
let unitquestion = aq.PropertySurvey
.AnsweredQuestions
.Where(x => x.QuestionID == c.UnitsQuestionID)
.FirstOrDefault()
where aq.QuestionID == c.QuestionID && a.ID == c.AnswerID
select new
{
QuestionText = aq.Question.Text,
AnswerText = a.Text,
UnitCost = c.Amount,
NumUnits = unitquestion == null ? 1 : unitquestion.IntegerAnswer ?? 1,
};
花了我很长时间才得到这个。我仍然认为在sql中我不禁会被Use Views in Entity Framework诱惑。请注意我已将其简化为仅显示第一个左侧连接到UnitQuestion