Skip to content

CSHARP-4976: MongoDB C# Driver no longer compatible with DevExpress ASP.NET Core Middleware #1291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 14, 2024

Conversation

sanych-sun
Copy link
Member

No description provided.

@sanych-sun sanych-sun requested a review from a team as a code owner March 13, 2024 19:17
@sanych-sun sanych-sun requested review from adelinowona and rstam and removed request for a team and adelinowona March 13, 2024 19:17
Copy link
Contributor

@rstam rstam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great detective work!

@@ -144,7 +147,31 @@ public override string ToString()
private BsonDocumentStagePipelineDefinition<TDocument, TOutput> CreateCollectionPipelineDefinition()
{
var stages = _pipeline.Stages.Select(s => (BsonDocument)s.Render());
return new BsonDocumentStagePipelineDefinition<TDocument, TOutput>(stages, (IBsonSerializer<TOutput>)_pipeline.OutputSerializer);
IBsonSerializer<TOutput> outputSerializer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move all this new code to a helper function (called GetOutputSerializer?) and call it from CreateDatabasePipelineDefinition also.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var stages = _pipeline.Stages.Select(s => (BsonDocument)s.Render());
var outputSerializer = GetOutputSerializer();
return new BsonDocumentStagePipelineDefinition<TDocument, TOutput>(stages, outputSerializer);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where GetOutputSerializer is:

private IBsonSerializer<TOutput> GetOutputSerializer()
{
    var outputSerializer = _pipeline.OutputSerializer;
    var outputType = outputSerializer.ValueType;

    if (outputType == typeof(TOutput))
    {
        return (IBsonSerializer<TOutput>)outputSerializer;
    }
    else if (typeof(TOutput).IsAssignableFrom(outputType))
    {
        if (typeof(TOutput).IsNullableOf(outputType))
        {
            return (IBsonSerializer<TOutput>)NullableSerializer.Create(outputSerializer);
        }
        else
        {
            return (IBsonSerializer<TOutput>)DowncastingSerializer.Create(
                typeof(TOutput),
                outputType,
                outputSerializer);
        }
    }
    else
    {
        throw new NotSupportedException($"The type of the pipeline output is {outputType} which is not assignable to {typeof(TOutput)}.");
    }
}

Note the new exception type and message.

throw new InvalidCastException($"Cannot represent {_pipeline.OutputSerializer.ValueType} as {typeof(TOutput)}.");
}

return new BsonDocumentStagePipelineDefinition<TDocument, TOutput>(stages, outputSerializer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor CreateDatabasePipelineDefinition to:

var stages = _pipeline.Stages.Select(s => (BsonDocument)s.Render());
var outputSerializer = GetOutputSerializer();
return new BsonDocumentStagePipelineDefinition<NoPipelineInput, TOutput>(stages, outputSerializer);

public class ExecutableQueryTests : Linq3IntegrationTest
{
[Fact]
public void Downcast_to_object_should_work()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the method name should be Cast_to_object_should_work.

Because the result of the expression is being cast to object.

Similarly for other test methods.

var queryable = collection.AsQueryable();

var results = queryable.Provider.CreateQuery<object>(queryable.Expression).AsEnumerable();
results.Count().Should().Be(5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clearly separate the Arrange/Act/Assert sections of the test:

var collection = GetCollection();
var queryable1 = collection.AsQueryable();
var queryable2 = queryable1.Provider.CreateQuery<object>(queryable1.Expression);

var results = queryable2.ToList();

results.Should().HaveCount(5);

(k, p) => new ProductAggregation() {Type = k, MaxPrice = p.Select(p => p.Price).Max()});

var results = queryable.Provider.CreateQuery<object>(queryable.Expression).AsEnumerable();
results.Count().Should().Be(2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var collection = GetCollection();
var queryable1 = collection.AsQueryable().GroupBy(
    p => p.Type,
    (k, p) => new ProductAggregation() {Type = k, MaxPrice = p.Select(p => p.Price).Max()});
var queryable2 = queryable1.Provider.CreateQuery<object>(queryable1.Expression);

var results = queryable2.ToList();

results.Should().HaveCount(2);

var queryable = collection.AsQueryable().Select(p => p.Id);

var results = queryable.Provider.CreateQuery<object>(queryable.Expression).AsEnumerable();
results.Count().Should().Be(5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var collection = GetCollection();
var queryable1 = collection.AsQueryable().Select(p => p.Id);
var queryable2 = queryable1.Provider.CreateQuery<object>(queryable1.Expression);

var results = queryable2.ToList();

results.Should().HaveCount(5);

var queryable = collection.AsQueryable().Select(p => p.Id);

var results = queryable.Provider.CreateQuery<int?>(queryable.Expression).AsEnumerable();
results.Count().Should().Be(5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var collection = GetCollection();
var queryable1 = collection.AsQueryable().Select(p => p.Id);
var queryable2 = queryable1.Provider.CreateQuery<int?>(queryable1.Expression);

var results = queryable2.ToList();

results.Should().HaveCount(5);

var queryable = collection.AsQueryable();

var exception = Record.Exception(() => queryable.Provider.CreateQuery<ProductAggregation>(queryable.Expression).AsEnumerable().ToList());
exception.Should().BeOfType<InvalidCastException>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var collection = GetCollection();
var queryable1 = collection.AsQueryable();
var queryable2 = queryable1.Provider.CreateQuery<ProductAggregation>(queryable1.Expression);

var exception = Record.Exception(() => queryable2.ToList());

exception.Should().BeOfType<NotSupportedException>();
exception.Message.Should().Contain($"The type of the pipeline output is {typeof(DerivedProduct)} which is not assignable to {typeof(ProductAggregation)}");

var queryable = collection.AsQueryable();

var results = queryable.Provider.CreateQuery<IProduct>(queryable.Expression).AsEnumerable();
results.Count().Should().Be(5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var collection = GetCollection();
var queryable1 = collection.AsQueryable();
var queryable2 = queryable1.Provider.CreateQuery<IProduct>(queryable1.Expression);

var results = queryable2.ToList();

results.Should().HaveCount(5);

var queryable = collection.AsQueryable();

var results = queryable.Provider.CreateQuery<ProductBase>(queryable.Expression).AsEnumerable();
results.Count().Should().Be(5);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var collection = GetCollection();
var queryable1 = collection.AsQueryable();
var queryable2 = queryable1.Provider.CreateQuery<ProductBase>(queryable1.Expression);

var results = queryable2.ToList();

results.Should().HaveCount(5);

@sanych-sun sanych-sun requested a review from rstam March 14, 2024 00:00
Copy link
Contributor

@rstam rstam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@sanych-sun sanych-sun merged commit 2803f87 into mongodb:master Mar 14, 2024
@sanych-sun sanych-sun deleted the csharp4976 branch March 14, 2024 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants