DarkWanderer / ClickHouse.Client

.NET client for ClickHouse
MIT License
325 stars 67 forks source link

[BUG] 7.9.0 throws an exeption #549

Open igor-tkachev opened 2 days ago

igor-tkachev commented 2 days ago

Current Behavior

Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> LinqToDB.LinqToDBException: Constructor not found in target type: ClickHouse.Client.Copy.ClickHouseBulkCopy..ctor(ClickHouseConnection)
   at LinqToDB.Expressions.TypeMapper.<>c.<ReplaceTypes>b__27_0(ReplaceTypesContext context, Expression e)
   at LinqToDB.Expressions.TransformVisitor`1.Transform(Expression expr)
   at LinqToDB.Expressions.ExpressionExtensions.Transform[TContext](Expression expr, TContext context, Func`3 func)
   at LinqToDB.Expressions.TypeMapper.ReplaceTypes(Expression expression, ReplaceTypesContext ctx)
   at LinqToDB.Expressions.TypeMapper.MapLambdaInternal(LambdaExpression lambda, Boolean mapConvert, Boolean convertResult, Boolean ignoreMissingMembers)
   at LinqToDB.Expressions.TypeMapper.BuildWrapperImpl(LambdaExpression lambda, Boolean wrapResult, Boolean optional, Type returnTypeOverride)
   at LinqToDB.Expressions.TypeMapper.BuildFactoryImpl[T](LambdaExpression lambda, Boolean wrapResult)
   at LinqToDB.Expressions.TypeMapper.BuildWrappedFactory[T,TR](Expression`1 newFunc)
   at LinqToDB.DataProvider.ClickHouse.ClickHouseProviderAdapter.CreateClientAdapter()
   at LinqToDB.DataProvider.ClickHouse.ClickHouseProviderAdapter.GetInstance(ClickHouseProvider provider)
   at LinqToDB.DataProvider.ClickHouse.ClickHouseMappingSchema.ClientMappingSchema..ctor()
   at LinqToDB.DataProvider.ClickHouse.ClickHouseDataProvider.GetMappingSchema(ClickHouseProvider provider)
   at LinqToDB.DataProvider.ClickHouse.ClickHouseDataProvider..ctor(String name, ClickHouseProvider provider)
   at LinqToDB.DataProvider.ClickHouse.ClickHouseClientDataProvider..ctor()
   at System.RuntimeType.CreateInstanceOfT()
   --- End of inner exception stack trace ---
   at System.RuntimeType.CreateInstanceOfT()
   at System.Activator.CreateInstance[T]()
   at LinqToDB.DataProvider.ProviderDetectorBase`2.<>c__1`1.<CreateDataProvider>b__1_0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at LinqToDB.DataProvider.ClickHouse.ClickHouseProviderDetector.GetDataProvider(ConnectionOptions options, ClickHouseProvider provider, Dialect version)
   at LinqToDB.DataProvider.ProviderDetectorBase`2.CreateOptions(DataOptions options, TVersion dialect, TProvider provider)
   at LinqToDB.DataOptionsExtensions.UseClickHouse(DataOptions options, ClickHouseProvider provider, Func`2 optionSetter)
   at LinqToDB.DataOptionsExtensions.UseClickHouse(DataOptions options, String connectionString, ClickHouseProvider provider, Func`2 optionSetter)
   at DataModels.ClickHouse.ClientHouseDB.GetDataOptions(String configString) in P:\LinqToDBTest\DataModels.cs:line 26
   at DataModels.ClickHouse.ClientHouseDB..ctor() in P:\LinqToDBTest\ClickHouseDB.generated.cs:line 42
   at LinqToDBTest.Program.Main(String[] args) in P:\LinqToDBTest\Program.cs:line 20

Expected Behavior

7.8.2 works just fine.

Steps To Reproduce

No response

Environment

- OS: Windows
- Runtime: net8.0

Anything else?

No response

igor-tkachev commented 2 days ago

7.8.3 works as well.

SMAH1 commented 2 days ago

I have same issue. After checking, I noticed that you have removed the default constructor of the ClickHouseBulkCopy class which takes only one parameter. So LinqToDB throw exception!

DarkWanderer commented 2 days ago

Thanks for report. Looks like unintended consequence of adding a default-value parameter to constructor - https://github.com/DarkWanderer/ClickHouse.Client/pull/541/files#diff-1d47bdcdc288905072a1548d31e9b8e961d40c9b904d2d947d2885276804a4aaR27

Please try package version 7.9.1

Can you share an example of code where this issue would be reproduced? I'll add it to unit tests

MaceWindu commented 1 day ago

@DarkWanderer, I don't think unit test will help with issues like that.

This specific issue caused by the way we consume ADO.NET providers in LinqToDB: all non-standard APIs are mapped using reflection as:

E.g. specific to this issue mapping is here

This approach breaks from time to time (like we have it here) when binary-incompatible (or behavior) API changes occur in provider and in general it is recommended to avoid such changes in non-major versions.

As solution I would recommend to add public API baselines to detect API breaking changes before they released using https://www.nuget.org/packages/Microsoft.CodeAnalysis.PublicApiAnalyzers