ServiceStack ORMLite联表查询主表别名及选择列最佳实现方法
ORMLite关联查询主表列时解决同名字段冲突的最简方法
问题背景
编写ORMLite关联查询时,需要通过次级表过滤数据、仅返回From<T>()指定主表的全部字段,初始查询代码如下:
var query = conn .From<SurveyQuestionOptionDTO>() .Join<SurveyQuestionDTO>((o, q) => o.SurveyQuestionId == q.Id, conn.JoinAlias("q")) .Where<SurveyQuestionDTO>(q => q.SurveyId == surveyId); return conn.Select(query);
生成的SQL因为主表SurveyQuestionOptions和关联表SurveyQuestions同时存在Id、Sequence同名字段,SELECT子句未加表限定名导致列引用歧义,执行报错:
SELECT "Id", "SurveyQuestionId", "Option", "Selected", "Sequence" FROM "dbo"."SurveyQuestionOptions" INNER JOIN "dbo"."SurveyQuestions" q ON ("dbo"."SurveyQuestionOptions"."SurveyQuestionId" = "q"."Id") WHERE ("dbo"."SurveyQuestions"."SurveyId" = @0)
临时方案是在Select中手动枚举主表所有字段,虽然能正常运行,但冗余代码多,后续表结构变更、DTO重新生成时必须同步修改查询逻辑,维护成本高:
var query = conn .From<SurveyQuestionOptionDTO>() .Join<SurveyQuestionDTO>( (o, q) => o.SurveyQuestionId == q.Id && q.SurveyId == surveyId, conn.JoinAlias("q")) .Select<SurveyQuestionOptionDTO>(o => new { o.Id, o.SurveyQuestionId, o.Option, o.Selected, o.Sequence }); return conn.Select(query);
推荐实现
不需要手动枚举字段,用ORMLite内置的API即可自动给主表字段加表前缀,避免列名冲突,两种写法都可以:
- 方案1:主表别名+通配符选择(最接近手写SQL习惯)
给主表设置别名,直接通过字符串通配符选择主表所有列,生成的SQL会自动给所有主表列加别名前缀,后续DTO新增字段无需修改查询代码:
var mainTableAlias = conn.JoinAlias("o"); var query = conn .From<SurveyQuestionOptionDTO>(mainTableAlias) .Join<SurveyQuestionDTO>((o, q) => o.SurveyQuestionId == q.Id, conn.JoinAlias("q")) .Where<SurveyQuestionDTO>(q => q.SurveyId == surveyId) .Select<SurveyQuestionOptionDTO>("o.*"); return conn.Select<SurveyQuestionOptionDTO>(query);
- 方案2:实体表达式选择(无硬编码别名)
不需要自定义别名,直接在Select中传入主表实体的表达式,ORMLite会自动给所有主表字段加上完整表名限定,从根源避免同名字段冲突:
var query = conn .From<SurveyQuestionOptionDTO>() .Join<SurveyQuestionDTO>((o, q) => o.SurveyQuestionId == q.Id, conn.JoinAlias("q")) .Where<SurveyQuestionDTO>(q => q.SurveyId == surveyId) .Select<SurveyQuestionOptionDTO>(o => o); return conn.Select(query);
提示:不建议把过滤条件写到Join的关联表达式中,ORMLite对Where子句的表别名解析逻辑更稳定,能减少别名不匹配的隐性问题。
内容的提问来源于stack exchange,提问作者Steve Crane
相关产品推荐
相关产品推荐

