UnresolvedJoinInfo represents the data source defined by a member access in a LINQ expression.
Inheritance: IJoinInfo
    public void ResolveSqlTable_ResolvesJoinInfo ()
    {
      var memberInfo = typeof (Kitchen).GetProperty ("Cook");
      var entityExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Kitchen));
      var unresolvedJoinInfo = new UnresolvedJoinInfo (entityExpression, memberInfo, JoinCardinality.One);
      var join = _sqlTable.GetOrAddLeftJoin (unresolvedJoinInfo, memberInfo);

      var fakeResolvedJoinInfo = SqlStatementModelObjectMother.CreateResolvedJoinInfo (typeof (Cook));

      using (_stageMock.GetMockRepository().Ordered())
      {
        _stageMock
            .Expect (mock => mock.ResolveTableInfo (_unresolvedTableInfo, _mappingResolutionContext))
            .Return (_fakeResolvedSimpleTableInfo);
        _stageMock
            .Expect (mock => mock.ResolveJoinInfo (join.JoinInfo, _mappingResolutionContext))
            .Return (fakeResolvedJoinInfo);
      }
      _stageMock.Replay();

      _visitor.ResolveSqlTable (_sqlTable);

      _stageMock.VerifyAllExpectations();
      Assert.That (join.JoinInfo, Is.SameAs (fakeResolvedJoinInfo));
    }
 public void SetUp ()
 {
   _resolverMock = MockRepository.GenerateStrictMock<IMappingResolver>();
   _unresolvedJoinInfo = SqlStatementModelObjectMother.CreateUnresolvedJoinInfo_KitchenCook();
   _generator = new UniqueIdentifierGenerator();
   _stageMock = MockRepository.GenerateStrictMock<IMappingResolutionStage> ();
   _mappingResolutionContext = new MappingResolutionContext();
 }
    public void ApplyContext_VisitUnresolvedJoinInfo ()
    {
      var entityExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook));
      var unresolvedJoinInfo = new UnresolvedJoinInfo (entityExpression, typeof (Cook).GetProperty ("ID"), JoinCardinality.One);
      
      var result = SqlContextJoinInfoVisitor.ApplyContext (unresolvedJoinInfo, SqlExpressionContext.ValueRequired, _stageMock, _mappingResolutionContext);

      Assert.That (result, Is.SameAs (unresolvedJoinInfo));
    }
    public void ResolveJoinInfo_ForeignKeyOnTheRight()
    {
      var customerTableInfo = new ResolvedSimpleTableInfo (typeof (DataContextTestClass.Customer), "dbo.Customers", "t1");
      var customerPrimaryKey = new SqlColumnDefinitionExpression (typeof (string), customerTableInfo.TableAlias, "CustomerID", true);
      var customerEntity = new SqlEntityDefinitionExpression (customerTableInfo.ItemType, customerTableInfo.TableAlias, null, e => e);

      var ordersMember = customerTableInfo.ItemType.GetProperty ("Orders");
      var unresolvedJoinInfo = new UnresolvedJoinInfo (customerEntity, ordersMember, JoinCardinality.Many);

      var resolvedJoinInfo = _mappingResolver.ResolveJoinInfo (unresolvedJoinInfo, _generator);

      var expectedOrderTableInfo = new ResolvedSimpleTableInfo (typeof (DataContextTestClass.Order), "dbo.Order", "t0");
      var expectedOrderForeignKey = new SqlColumnDefinitionExpression (typeof (string), expectedOrderTableInfo.TableAlias, "CustomerID", false);
      SqlExpressionTreeComparer.CheckAreEqualTrees (Expression.Equal (customerPrimaryKey, expectedOrderForeignKey), resolvedJoinInfo.JoinCondition);

      Assert.That (resolvedJoinInfo.ItemType, Is.EqualTo (expectedOrderTableInfo.ItemType));
      Assert.That (resolvedJoinInfo.ForeignTableInfo.ItemType, Is.EqualTo (expectedOrderTableInfo.ItemType));
      Assert.That (resolvedJoinInfo.ForeignTableInfo.TableAlias, Is.EqualTo (expectedOrderTableInfo.TableAlias));
    }
 public static SqlJoinedTable CreateSqlJoinedTable_WithUnresolvedJoinInfo ()
 {
   var entityExpression = CreateSqlEntityDefinitionExpression (typeof (Cook));
   var joinInfo = new UnresolvedJoinInfo (entityExpression, typeof (Cook).GetProperty ("FirstName"), JoinCardinality.One);
   return new SqlJoinedTable (joinInfo, JoinSemantics.Left);
 }
    public void ResolveJoinInfo_ShouldThrowUnmappedExceptionForMember ()
    {
      var customerTableInfo = new ResolvedSimpleTableInfo (typeof (DataContextTestClass.Customer), "dbo.Customers", "t1");

      var customerDefinition = new SqlEntityDefinitionExpression (customerTableInfo.ItemType, customerTableInfo.TableAlias, null, e => e);

      var joinInfo = new UnresolvedJoinInfo (customerDefinition, _unmappedInfo, JoinCardinality.One);

      _mappingResolver.ResolveJoinInfo (joinInfo, _generator);
    }
    public void ResolveJoinInfo_OneNullableColumn_TheOtherNot_LeadsToConversion ()
    {
      var regionTableInfo = new ResolvedSimpleTableInfo (typeof (DataContextTestClass.Region), "dbo.Regions", "t1");
      var regionEntity = new SqlEntityDefinitionExpression (regionTableInfo.ItemType, regionTableInfo.TableAlias, null, e => e);

      var territoriesMember = regionTableInfo.ItemType.GetProperty ("Territories");
      var unresolvedJoinInfo = new UnresolvedJoinInfo (regionEntity, territoriesMember, JoinCardinality.Many);

      var resolvedJoinInfo = _mappingResolver.ResolveJoinInfo (unresolvedJoinInfo, _generator);

      var regionPrimaryKey = new SqlColumnDefinitionExpression (typeof (int), regionTableInfo.TableAlias, "RegionID", true);
      var expectedTerritoryTableInfo = new ResolvedSimpleTableInfo (typeof (DataContextTestClass.Territory), "dbo.Territories", "t0");
      var expectedTerritoryForeignKey = new SqlColumnDefinitionExpression (typeof (int?), expectedTerritoryTableInfo.TableAlias, "RegionID", false);
      SqlExpressionTreeComparer.CheckAreEqualTrees (
          Expression.Equal (
            Expression.Convert (regionPrimaryKey, typeof (int?)), 
            expectedTerritoryForeignKey), resolvedJoinInfo.JoinCondition);
    }
 IJoinInfo IJoinInfoVisitor.VisitUnresolvedJoinInfo (UnresolvedJoinInfo tableSource)
 {
   throw new InvalidOperationException ("UnresolvedJoinInfo is not valid at this point.");
 }
    public IJoinInfo VisitUnresolvedCollectionJoinInfo (UnresolvedCollectionJoinInfo joinInfo)
    {
      ArgumentUtility.CheckNotNull ("joinInfo", joinInfo);

      var resolvedExpression = _stage.ResolveCollectionSourceExpression (joinInfo.SourceExpression, _context);
      while (resolvedExpression is UnaryExpression)
        resolvedExpression = _stage.ResolveCollectionSourceExpression (((UnaryExpression)resolvedExpression).Operand, _context);

      var resolvedExpressionAsEntity = resolvedExpression as SqlEntityExpression;

      if (resolvedExpressionAsEntity != null)
      {
        var unresolvedJoinInfo = new UnresolvedJoinInfo (resolvedExpressionAsEntity, joinInfo.MemberInfo, JoinCardinality.Many);
        return unresolvedJoinInfo.Accept (this);
      }

      var message = string.Format (
          "Only entities can be used as the collection source in from expressions, '{0}' cannot. Member: '{1}'",
          FormattingExpressionTreeVisitor.Format (resolvedExpression),
          joinInfo.MemberInfo);
      throw new NotSupportedException (message);
    }
    public ResolvedJoinInfo ResolveJoinInfo (UnresolvedJoinInfo joinInfo, UniqueIdentifierGenerator generator)
    {
      if (joinInfo.MemberInfo.DeclaringType == typeof (Cook))
      {
        switch (joinInfo.MemberInfo.Name)
        {
          case "Substitution":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "ID",
                typeof (int),
                true,
                CreateResolvedTableInfo (joinInfo.ItemType, generator),
                "SubstitutedID",
                typeof (int),
                false);
          case "Substituted":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "SubstitutedID",
                typeof (int),
                false,
                CreateResolvedTableInfo (joinInfo.ItemType, generator),
                "ID",
                typeof (int),
                true);
          case "Assistants":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "ID",
                typeof (int),
                true,
                CreateResolvedTableInfo (joinInfo.ItemType, generator),
                "AssistedID",
                typeof (int),
                false);
          case "Kitchen":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "KitchenID",
                typeof (int),
                false,
                CreateResolvedTableInfo (joinInfo.ItemType, generator),
                "ID",
                typeof (int),
                true);
          case "Knife":
            var joinedTableInfo = CreateResolvedTableInfo (joinInfo.ItemType, generator);
            var leftKey = ResolveMemberExpression (joinInfo.OriginatingEntity, typeof (Cook).GetProperty ("KnifeID"));
            var rightKey = ResolveSimpleTableInfo (joinedTableInfo, generator).GetIdentityExpression();
            return new ResolvedJoinInfo (joinedTableInfo, Expression.Equal (leftKey, rightKey));
        }
      }
      else if (joinInfo.MemberInfo.DeclaringType == typeof (Kitchen))
      {
        switch (joinInfo.MemberInfo.Name)
        {
          case "Cook":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "ID", typeof (int), true, CreateResolvedTableInfo (joinInfo.ItemType, generator), "KitchenID", typeof (int), false);
          case "Restaurant":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "RestaurantID", typeof (int), false, CreateResolvedTableInfo (joinInfo.ItemType, generator), "ID", typeof (int), true);
        }
      }
      else if (joinInfo.MemberInfo.DeclaringType == typeof (Restaurant))
      {
        switch (joinInfo.MemberInfo.Name)
        {
          case "SubKitchen":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "ID", typeof (int), true, CreateResolvedTableInfo (joinInfo.ItemType, generator), "RestaurantID", typeof (int), false);
          case "Cooks":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "ID", typeof (int), true, CreateResolvedTableInfo (joinInfo.ItemType, generator), "RestaurantID", typeof (int), false);
          case "CompanyIfAny":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "CompanyID",
                typeof (int?), 
                false, 
                CreateResolvedTableInfo (joinInfo.ItemType, generator), 
                "ID", 
                typeof (int), 
                true);

        }
      }
      else if (joinInfo.MemberInfo.DeclaringType == typeof (Company))
      {
        switch (joinInfo.MemberInfo.Name)
        {
          case "AllRestaurants":
            return CreateResolvedJoinInfo (
                joinInfo.OriginatingEntity,
                "ID",
                typeof (int), true, CreateResolvedTableInfo (joinInfo.ItemType, generator), "CompanyID", typeof (int?), false);
        }
      }

      throw new UnmappedItemException ("Member " + joinInfo.MemberInfo + " is not a valid join member.");
    }
 public void ItemType_CardinalityMany ()
 {
   var entityExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Restaurant));
   var joinInfo = new UnresolvedJoinInfo (entityExpression, typeof (Restaurant).GetProperty ("Cooks"), JoinCardinality.Many);
   Assert.That (joinInfo.ItemType, Is.SameAs (typeof (Cook)));
 }
 public void ItemType_CardinalityOne ()
 {
   var joinInfo = new UnresolvedJoinInfo (_entityExpression, typeof (Cook).GetProperty ("Substitution"), JoinCardinality.One);
   Assert.That (joinInfo.ItemType, Is.SameAs (typeof (Cook)));
 }
    public void ResolveSqlTable_ResolvesJoinInfo_Recursive ()
    {
      var memberInfo1 = typeof (Kitchen).GetProperty ("Cook");
      var entityExpression1 = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Kitchen));
      var unresolvedJoinInfo1 = new UnresolvedJoinInfo (entityExpression1, memberInfo1, JoinCardinality.One);
      var memberInfo2 = typeof (Cook).GetProperty ("Substitution");
      var entityExpression2 = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook));
      var unresolvedJoinInfo2 = new UnresolvedJoinInfo (entityExpression2, memberInfo2, JoinCardinality.One);
      var memberInfo3 = typeof (Cook).GetProperty ("Name");
      var entityExpression3 = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Cook));
      var unresolvedJoinInfo3 = new UnresolvedJoinInfo (entityExpression3, memberInfo3, JoinCardinality.One);
      
      var join1 = _sqlTable.GetOrAddLeftJoin (unresolvedJoinInfo1, memberInfo1);
      var join2 = join1.GetOrAddLeftJoin (unresolvedJoinInfo2, memberInfo2);
      var join3 = join1.GetOrAddLeftJoin (unresolvedJoinInfo3, memberInfo3);

      var fakeResolvedJoinInfo1 = SqlStatementModelObjectMother.CreateResolvedJoinInfo (typeof (Cook));
      var fakeResolvedJoinInfo2 = SqlStatementModelObjectMother.CreateResolvedJoinInfo (typeof (Cook));
      var fakeResolvedJoinInfo3 = SqlStatementModelObjectMother.CreateResolvedJoinInfo (typeof (string));

      using (_stageMock.GetMockRepository().Ordered())
      {
        _stageMock
            .Expect (mock => mock.ResolveTableInfo (_unresolvedTableInfo, _mappingResolutionContext))
            .Return (_fakeResolvedSimpleTableInfo);
        _stageMock
            .Expect (mock => mock.ResolveJoinInfo (join1.JoinInfo, _mappingResolutionContext))
            .Return (fakeResolvedJoinInfo1);
        _stageMock
            .Expect (mock => mock.ResolveJoinInfo (join2.JoinInfo, _mappingResolutionContext))
            .Return (fakeResolvedJoinInfo2);
        _stageMock
            .Expect (mock => mock.ResolveJoinInfo (join3.JoinInfo, _mappingResolutionContext))
            .Return (fakeResolvedJoinInfo3);
      }
      _stageMock.Replay();

      _visitor.ResolveSqlTable (_sqlTable);

      _stageMock.VerifyAllExpectations();
      Assert.That (join1.JoinInfo, Is.SameAs (fakeResolvedJoinInfo1));
      Assert.That (join2.JoinInfo, Is.SameAs (fakeResolvedJoinInfo2));
      Assert.That (join3.JoinInfo, Is.SameAs (fakeResolvedJoinInfo3));
    }
    public IJoinInfo VisitUnresolvedJoinInfo (UnresolvedJoinInfo joinInfo)
    {
      ArgumentUtility.CheckNotNull ("joinInfo", joinInfo);

      return joinInfo;
    }
    public virtual Expression VisitSqlEntityRefMemberExpression (SqlEntityRefMemberExpression expression)
    {
      ArgumentUtility.CheckNotNull ("expression", expression);

      if (!_resolveEntityRefMemberExpressions)
        return VisitExtensionExpression (expression);

      var unresolvedJoinInfo = new UnresolvedJoinInfo (expression.OriginatingEntity, expression.MemberInfo, JoinCardinality.One);
      // No revisiting required since this visitor does not handle ISqlEntityExpressions.
      return _stage.ResolveEntityRefMemberExpression (expression, unresolvedJoinInfo, _context);
    }
    public void GenerateSql_WithUnresolvedJoinInfo ()
    {
      var originalTable = new SqlTable (new ResolvedSimpleTableInfo (typeof (Cook), "CookTable", "c"), JoinSemantics.Inner);
      var kitchenCookMember = typeof (Kitchen).GetProperty ("Cook");
      var entityExpression = SqlStatementModelObjectMother.CreateSqlEntityDefinitionExpression (typeof (Kitchen));
      var unresolvedJoinInfo = new UnresolvedJoinInfo (entityExpression, kitchenCookMember, JoinCardinality.One);

      originalTable.GetOrAddLeftJoin (unresolvedJoinInfo, kitchenCookMember);

      Assert.That (
          () => SqlTableAndJoinTextGenerator.GenerateSql (originalTable, _commandBuilder, _stageMock, false),
          Throws.TypeOf<InvalidOperationException>().With.Message.EqualTo ("UnresolvedJoinInfo is not valid at this point."));
    }
    private Expression GetIdentityExpressionForReferencedEntity (SqlEntityRefMemberExpression expression)
    {
      var optimizedIdentity = _resolver.TryResolveOptimizedIdentity (expression);
      if (optimizedIdentity != null)
        return optimizedIdentity;

      var unresolvedJoinInfo = new UnresolvedJoinInfo (expression.OriginatingEntity, expression.MemberInfo, JoinCardinality.One);
      return _stage.ResolveEntityRefMemberExpression (expression, unresolvedJoinInfo, _context).GetIdentityExpression ();
    }
 public IJoinInfo VisitUnresolvedJoinInfo (UnresolvedJoinInfo joinInfo)
 {
   ArgumentUtility.CheckNotNull ("joinInfo", joinInfo);
   var result = _resolver.ResolveJoinInfo (joinInfo, _generator);
   return result.Accept (this);
 }