2014-06-20 69 views
1

我創建了一個包裝在我的數據訪問在OrmLite連接。ServiceStack Ormlite加入包裝

我現在越來越異常:

的System.Exception:表達式應該只有一個列

我的所有實體的有一個基類BaseEntity的。 JoinType只是一個包含列,選擇和連接位置的外觀。

我的包裝如下:

public IEnumerable<TResultEntity> Join<TResultEntity>(IList<JoinType<BaseEntity, BaseEntity>> joins) 
     { 
      var result = new List<TResultEntity>(); 

      if (joins != null && joins.Any()) 
      { 
       var joinBuilder = new JoinSqlBuilder<T, BaseEntity>(); 

       foreach (var join in joins) 
       { 
        joinBuilder = joinBuilder.Join(join.LeftColumn, join.RightColumn, join.LeftSelection, join.RightSelection, join.LeftWhere, join.RightWhere); 
       } 

       var connection = this.DataConnection; 
       using (connection) 
       { 
        var joinSql = joinBuilder.SelectDistinct().ToSql(); 
        result = connection.SqlList<TResultEntity>(joinSql); 
       } 
      } 

      return result; 
     } 

做同樣的事情,如果沒有列表似乎工作:

public IEnumerable<TResultEntity> Join<TLeftTable1, TRightTable1, TLeftTable2, TRightTable2, TResultEntity>(
      JoinType<TLeftTable1, TRightTable1> join1, 
      JoinType<TLeftTable2, TRightTable2> join2) 
      where TLeftTable1 : BaseEntity 
      where TRightTable1 : BaseEntity 
      where TLeftTable2 : BaseEntity 
      where TRightTable2 : BaseEntity 

編輯 - 我用下面的撥測:

// Act 
       var join1 = new JoinType<AnswerEntity, UserSurveyStateEntity>(
       l => l.OwnerId, 
       r => r.UserId, 
       x => new { UserId = x.OwnerId, x.QuestionId, AnswerId = x.Id, x.AnswerValue }); 

       var join2 = new JoinType<SurveyEntity, UserSurveyStateEntity>(
       l => l.Id, 
       r => r.SurveyInstanceId, 
       x => new { SurveyId = x.Id, SurveyName = x.Name, x.StatusValue }, 
       null, 
       null, 
       x => x.StatusValue == (int)UserSurveyStatus.Complete); 

       var joins = new List<JoinType<BaseEntity, BaseEntity>>(); 
       joins.Add(join1.As<JoinType<BaseEntity, BaseEntity>>()); 
       joins.Add(join2.As<JoinType<BaseEntity, BaseEntity>>()); 

       var result = dataAccess.Join<AnswerEntity>(joins).ToList(); 
+0

它炸燬在哪一行? – wbennett

+0

@wbennett joinBuilder = joinBuilder.Join(join.LeftColumn,join.RightColumn,join.LeftSelection,join.RightSelection,join.LeftWhere,join.RightWhere); – Bob

+0

什麼ormlite方言提供者? – wbennett

回答

2

編輯 - 現在看到的使用情況下,錯誤與澆鑄g添加到基本類型,而構建器爲具體BaseEntity存儲多個列選擇器。考慮添加一個抽象的JoinType類,並修改JoinType類,以便將它應用於構建器的聯接。

例如:

public class Entity 
    { 
     public string Id { get; set; } 
    } 
    public class Foo 
     : Entity 
    { 
     public string Value { get; set; } 
    } 

    public class Bar 
     : Entity 
    { 
     public string FooId { get; set; } 
     public string Value { get; set; } 
    } 

    public abstract class JoinType 
    { 
     public abstract JoinSqlBuilder<TNew, TBase> ApplyJoin<TNew, TBase>(
      JoinSqlBuilder<TNew, TBase> bldr); 
    } 

    public class JoinType<TSource, TTarget> 
     : JoinType 
    { 
     private Expression<Func<TSource, object>> _sourceColumn; 
     private Expression<Func<TTarget, object>> _destinationColumn; 
     private Expression<Func<TSource, object>> _sourceTableColumnSelection; 
     private Expression<Func<TTarget, object>> _destinationTableColumnSelection; 
     private Expression<Func<TSource, bool>> _sourceWhere; 
     private Expression<Func<TTarget, bool>> _destinationWhere; 

     public JoinType(Expression<Func<TSource, object>> sourceColumn, 
      Expression<Func<TTarget, object>> destinationColumn, 
      Expression<Func<TSource, object>> 
       sourceTableColumnSelection = null, 
      Expression<Func<TTarget, object>> 
       destinationTableColumnSelection = null, 
      Expression<Func<TSource, bool>> sourceWhere = null, 
      Expression<Func<TTarget, bool>> destinationWhere = 
       null) 
     { 
      this._sourceColumn = sourceColumn; 
      this._destinationColumn = destinationColumn; 
      this._sourceTableColumnSelection = sourceTableColumnSelection; 
      this._destinationTableColumnSelection = 
       destinationTableColumnSelection; 
      this._sourceWhere = sourceWhere; 
      this._destinationWhere = destinationWhere; 
     } 

     public override JoinSqlBuilder<TNew, TBase> ApplyJoin<TNew, TBase>(
      JoinSqlBuilder<TNew, TBase> bldr) 
     { 
      bldr.Join(_sourceColumn, 
       _destinationColumn, 
       _sourceTableColumnSelection, 
       _destinationTableColumnSelection, 
       _sourceWhere, 
       _destinationWhere); 

      return bldr; 
     } 
    } 

    public class FooBar 
    { 
     [References(typeof(Foo))] 
     public string FooId { get; set; } 
     [References(typeof(Bar))] 
     public string BarId { get; set; } 
     [References(typeof(Foo))] 
     public string FooValue { get; set; } 
     [References(typeof(Bar))] 
     public string BarValue { get; set; } 
    } 

    /* 
    This join accomplishes the same thing, but just returns the SQL as a string. 
    */ 
    public string Join<TResultEntity,TBase>(IList<JoinType>joins) 
    { 
     var result = new List<TResultEntity>(); 

     if (joins != null && joins.Any()) 
     { 
      var joinBuilder = new JoinSqlBuilder<TResultEntity, TBase>(); 

      foreach (var joinType in joins) 
      { 
       //call the apply join, and the join type will know the valid types 
       joinBuilder = joinType.ApplyJoin(joinBuilder); 
      } 

      return joinBuilder.SelectDistinct().ToSql(); 
     } 

     return null; 
    } 

    [TestMethod] 
    public void TestMethod1() 
    { 
     OrmLiteConfig.DialectProvider = SqlServerDialect.Provider; 

     var joins = new List<JoinType>(); 

     var jointype1 = new JoinType<Bar, FooBar>(
      bar => bar.Id, 
      bar => bar.BarId, 
      bar => new { BarId = bar.Id, BarValue = bar.Value } 
      ); 
     joins.Add(jointype1); 
     var joinType2 = new JoinType<Foo, FooBar>(
      foo => foo.Id, 
      bar => bar.FooId, 
      foo => new { FooId = foo.Id, FooValue = foo.Value} 
      ); 
     joins.Add(joinType2); 

     var str = Join<FooBar, Bar>(joins); 
    } 

老回答 - 這個錯誤是由您選擇join.LeftColumn或您的join.RightColumn包含兩個選擇導致錯誤

仍然具有現實意義。確保他們只包含一個。

我能夠重現錯誤與下面的測試:

public class Entity 
    { 
     public string Id { get; set; } 
    } 
    public class Foo 
     : Entity 
    { 
     public string Value { get; set; } 
    } 

    public class Bar 
     : Entity 
    { 
     public string FooId { get; set; } 
     public string Value { get; set; } 
    } 

    public class FooBar 
    { 
     [References(typeof(Foo))] 
     public string FooId { get; set; } 
     [References(typeof(Bar))] 
     public string BarId { get; set; } 
     [References(typeof(Foo))] 
     public string FooValue { get; set; } 
     [References(typeof(Bar))] 
     public string BarValue { get; set; } 
    } 

    [TestMethod] 
    public void TestMethod1() 
    { 
     OrmLiteConfig.DialectProvider = SqlServerDialect.Provider; 
     var bldr = new JoinSqlBuilder<FooBar,Bar>(); 
     bldr = bldr.Join<FooBar, Bar>(
      bar => bar.BarId, 
      bar => new { Id1 = bar.Id, Id2 = bar.Id},//<-- this should only contain a single member 
      bar => new { BarId =bar.BarId }, 
      bar => new { BarId = bar.Id, BarValue = bar.Value}, 
      bar => bar.BarId != null, 
      bar => bar.Id != null 
      ); 

     var str = bldr.SelectDistinct().ToSql(); 
    } 
+0

對於具有相同源和目標的連接列表,這將工作正常。如果我有不同的目標和來源,它不會工作。例如 - UserEntity + QuestionEntity&QuestionEntity + AnswerEntity。 – Bob

+0

好的。看到我修改後的答案,說明你爲什麼會得到這種例外。確保前兩個參數不包含多個成員表達式。 – wbennett

+0

我在想這是因爲我以某種方式將我的實體投射回基類。 – Bob